From cvs at cvs.gnupg.org Mon Jan 3 14:18:32 2011 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 03 Jan 2011 14:18:32 +0100 Subject: [svn] w32pth - r48 - trunk Message-ID: Author: wk Date: 2011-01-03 14:18:31 +0100 (Mon, 03 Jan 2011) New Revision: 48 Added: trunk/README Removed: trunk/AUTHORS trunk/COPYING.LESSER trunk/ChangeLog trunk/INSTALL trunk/Makefile.am trunk/NEWS trunk/README trunk/README.SVN trunk/THANKS trunk/TODO trunk/autogen.sh trunk/compile trunk/config.guess trunk/config.sub trunk/configure.ac trunk/debug.h trunk/depcomp trunk/install-sh trunk/libw32pth.def trunk/ltmain.sh trunk/m4/ trunk/missing trunk/pth-config.in trunk/pth.h trunk/utils.h trunk/versioninfo.rc.in trunk/w32-io.c trunk/w32-io.h trunk/w32-pth.c Log: Migrated to GIT; see README. From cvs at cvs.gnupg.org Mon Jan 3 14:59:02 2011 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 03 Jan 2011 14:59:02 +0100 Subject: [svn] pinentry - r243 - in trunk: . qt qt4 w32 Message-ID: Author: wk Date: 2011-01-03 14:59:01 +0100 (Mon, 03 Jan 2011) New Revision: 243 Added: trunk/README Removed: trunk/AUTHORS trunk/COPYING trunk/ChangeLog trunk/INSTALL trunk/Makefile.am trunk/Manifest trunk/NEWS trunk/README trunk/README.SVN trunk/THANKS trunk/TODO trunk/acinclude.m4 trunk/assuan/ trunk/autogen.sh trunk/config.guess trunk/config.rpath trunk/config.sub trunk/configure.ac trunk/curses/ trunk/debian/ trunk/depcomp trunk/doc/ trunk/gtk+-2/ trunk/gtk/ trunk/install-sh trunk/m4/ trunk/missing trunk/mkinstalldirs trunk/pinentry/ trunk/qt/Makefile.am trunk/qt/Manifest trunk/qt/README.SecQ trunk/qt/main.cpp trunk/qt/pinentrydialog.cpp trunk/qt/pinentrydialog.h trunk/qt/secqinternal.cpp trunk/qt/secqinternal_p.h trunk/qt/secqlineedit.cpp trunk/qt/secqlineedit.h trunk/qt/secqstring.cpp trunk/qt/secqstring.h trunk/qt4/Makefile.am trunk/qt4/document-encrypt.png trunk/qt4/main.cpp trunk/qt4/pinentry.qrc trunk/qt4/pinentrydialog.cpp trunk/qt4/pinentrydialog.h trunk/qt4/pinentrydialog.moc trunk/qt4/qrc_pinentry.cpp trunk/qt4/qsecurelineedit.cpp trunk/qt4/qsecurelineedit.h trunk/qt4/qsecurelineedit.moc trunk/qt4/qsecurelineedit_p.h trunk/qt4/secstring.cpp trunk/qt4/secstring.h trunk/w32/Makefile.am trunk/w32/Manifest trunk/w32/main.c trunk/w32/pinentry-w32.rc trunk/w32/resource.h Log: Migrated to git; see README. From cvs at cvs.gnupg.org Mon Jan 3 15:35:27 2011 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 03 Jan 2011 15:35:27 +0100 Subject: [svn] GpgEX - r87 - trunk Message-ID: Author: wk Date: 2011-01-03 15:35:27 +0100 (Mon, 03 Jan 2011) New Revision: 87 Added: trunk/README Removed: trunk/ABOUT-NLS trunk/AUTHORS trunk/COPYING.LESSER trunk/ChangeLog trunk/INSTALL trunk/Makefile.am trunk/NEWS trunk/README trunk/TODO trunk/autogen.sh trunk/config.guess trunk/config.rpath trunk/config.sub trunk/configure.ac trunk/depcomp trunk/doc/ trunk/install-sh trunk/m4/ trunk/missing trunk/mkinstalldirs trunk/po/ trunk/src/ Log: Migrated to git; see README From cvs at cvs.gnupg.org Mon Jan 3 15:58:40 2011 From: cvs at cvs.gnupg.org (svn author wk) Date: Mon, 03 Jan 2011 15:58:40 +0100 Subject: [svn] GpgOL - r337 - trunk Message-ID: Author: wk Date: 2011-01-03 15:58:40 +0100 (Mon, 03 Jan 2011) New Revision: 337 Added: trunk/README Removed: trunk/ABOUT-NLS trunk/AUTHORS trunk/COPYING.LESSER trunk/ChangeLog trunk/INSTALL trunk/Makefile.am trunk/NEWS trunk/README trunk/TODO trunk/autogen.sh trunk/config.guess trunk/config.rpath trunk/config.sub trunk/configure.ac trunk/depcomp trunk/doc/ trunk/forms/ trunk/gpgol-assuan-abi-2.patch trunk/install-sh trunk/m4/ trunk/missing trunk/mkinstalldirs trunk/po/ trunk/src/ trunk/tests/ Log: Migrated to git; see README From cvs at cvs.gnupg.org Mon Jan 3 18:02:23 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 03 Jan 2011 18:02:23 +0100 Subject: [git] Pinentry - The standard pinentry collection branch, master, updated. pinentry-0.8.1-1-g5190773 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The standard pinentry collection". The branch, master has been updated via 5190773293bc38550bbc8aeb1b539bfb47a47c78 (commit) from 568752d51660a23041650d37674adb89fbd3bd94 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 5190773293bc38550bbc8aeb1b539bfb47a47c78 Author: Werner Koch Date: Mon Jan 3 17:44:07 2011 +0100 Append a git commit id. diff --git a/configure.ac b/configure.ac index fe5904e..4b8ed79 100644 --- a/configure.ac +++ b/configure.ac @@ -31,15 +31,18 @@ min_automake_version="1.10" # specific feature can already be done under the assumption that the # SVN version is the most recent one in a branch. To disable the SVN # version for the real release, set the my_issvn macro to no. -m4_define(my_version, [0.8.1]) -m4_define(my_issvn, [no]) +m4_define(my_version, [0.8.2]) +m4_define(my_issvn, [yes]) m4_define([svn_revision], m4_esyscmd([printf "%d" $(svn info 2>/dev/null \ | sed -n '/^Revision:/ s/[^0-9]//gp'|head -1)])) +m4_define([git_revision], m4_esyscmd([git branch -v 2>/dev/null \ + | awk '/^\* / {printf "%s",$3}'])) # Remember to remove the "-cvs" suffix *before* a release and to bump the # version number immediately *after* a release and to re-append the suffix. AC_INIT(pinentry, - [my_version[]m4_if(my_issvn,[yes],[-svn[]svn_revision])], + [my_version[]m4_if(my_issvn,[yes], + [m4_if(git_revision,[],[-svn[]svn_revision],[-git[]git_revision])])], [gnupg-devel at gnupg.org]) AM_CONFIG_HEADER(config.h) AC_CONFIG_SRCDIR(pinentry/pinentry.h) ----------------------------------------------------------------------- Summary of changes: configure.ac | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) hooks/post-receive -- The standard pinentry collection http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jan 3 19:14:53 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 03 Jan 2011 19:14:53 +0100 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta1-29-gdc5d9b1 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, master has been updated via dc5d9b140094ce5a89216119c34303ea48358c26 (commit) from e1ff8863bbdf5a1d42f7e9d29997b34e7154af5e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit dc5d9b140094ce5a89216119c34303ea48358c26 Author: Werner Koch Date: Mon Jan 3 18:56:41 2011 +0100 Rename README.SVN also in Makefile diff --git a/ChangeLog b/ChangeLog index e765ef8..656fe72 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-01-03 Werner Koch + + * README.SVN: Rename to README.GIT. + * Makefile.am (EXTRA_DIST): Adjust for that change. + 2010-12-14 Werner Koch * configure.ac (BUILD_WITH_GPG, BUILD_WITH_GPGSM) diff --git a/Makefile.am b/Makefile.am index 5776413..c5c2a01 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ -# Makefile.am - main makefile for NewPG/GnuPG -# Copyright (C) 2001, 2004 Free Software Foundation, Inc. +# Makefile.am - main makefile for GnuPG +# Copyright (C) 2001, 2004, 2010 Free Software Foundation, Inc. # # This file is part of GnuPG. # @@ -22,7 +22,7 @@ ACLOCAL_AMFLAGS = -I m4 -I gl/m4 AUTOMAKE_OPTIONS = dist-bzip2 no-dist-gzip DISTCHECK_CONFIGURE_FLAGS = --enable-symcryptrun --enable-mailto -EXTRA_DIST = scripts/config.rpath scripts/potomo autogen.sh README.SVN +EXTRA_DIST = scripts/config.rpath scripts/potomo autogen.sh README.GIT DISTCLEANFILES = g10defs.h if BUILD_GPGSM ----------------------------------------------------------------------- Summary of changes: ChangeLog | 5 +++++ Makefile.am | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Tue Jan 4 11:24:31 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 04 Jan 2011 11:24:31 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.4.4-49-gde7bd12 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via de7bd128995c9cf6e471d1bb16cf4a2f80262c96 (commit) from 294eb3d5838830b777c3b412b3f3188e0962e588 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit de7bd128995c9cf6e471d1bb16cf4a2f80262c96 Author: Werner Koch Date: Tue Jan 4 11:05:13 2011 +0100 Makefile.am (LDADD): Fix typo in last change. Reported by Andrey Jivsov. diff --git a/tests/ChangeLog b/tests/ChangeLog index e272110..64bad3e 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,8 @@ +2011-01-04 Werner Koch + + * Makefile.am (LDADD): Fix typo in last change. Reported by + Andrey Jivsov. + 2010-07-19 Werner Koch * Makefile.am (LDADD): Add GPG_ERROR_LIBS to help a new wannabe ld. diff --git a/tests/Makefile.am b/tests/Makefile.am index f334acb..59cc5c4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -36,7 +36,7 @@ TESTS += benchmark AM_CPPFLAGS = -I../src -I$(top_srcdir)/src AM_CFLAGS = $(GPG_ERROR_CFLAGS) -LDADD = ../src/libgcrypt.la $(DL_LIBS) ../compat/libcompat.la $(GPG_ERROR_LIB) +LDADD = ../src/libgcrypt.la $(DL_LIBS) ../compat/libcompat.la $(GPG_ERROR_LIBS) EXTRA_PROGRAMS = testapi pkbench noinst_PROGRAMS = $(TESTS) fipsdrv rsacvt ----------------------------------------------------------------------- Summary of changes: tests/ChangeLog | 5 +++++ tests/Makefile.am | 2 +- 2 files changed, 6 insertions(+), 1 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Wed Jan 5 09:33:01 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 05 Jan 2011 09:33:01 +0100 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta1-30-g7d24ffa Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, master has been updated via 7d24ffaf805074fce14fed0b22e413cf5ca00024 (commit) from dc5d9b140094ce5a89216119c34303ea48358c26 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 7d24ffaf805074fce14fed0b22e413cf5ca00024 Author: Werner Koch Date: Wed Jan 5 09:14:11 2011 +0100 Support the gnuk token pinpad code. diff --git a/scd/ChangeLog b/scd/ChangeLog index 41c64a5..41a0f76 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,7 @@ +2011-01-05 Werner Koch + + * ccid-driver.c (ccid_transceive_secure): Support the gnuk token. + 2010-11-16 Werner Koch * apdu.c (PCSC_UNKNOWN) [W32]: Fix all these values which don't diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index b71ff6a..98268c0 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -209,7 +209,8 @@ enum { VENDOR_SCM = 0x04e6, VENDOR_OMNIKEY= 0x076b, VENDOR_GEMPC = 0x08e6, - VENDOR_KAAN = 0x0d46 + VENDOR_KAAN = 0x0d46, + VENDOR_FSIJ = 0x234B }; /* A list and a table with special transport descriptions. */ @@ -3072,6 +3073,7 @@ ccid_transceive_secure (ccid_driver_t handle, { case VENDOR_SCM: /* Tested with SPR 532. */ case VENDOR_KAAN: /* Tested with KAAN Advanced (1.02). */ + case VENDOR_FSIJ: /* Tested with the gnuk code (2011-01-05). */ break; case VENDOR_CHERRY: /* The CHERRY XX44 keyboard echos an asterisk for each entered ----------------------------------------------------------------------- Summary of changes: scd/ChangeLog | 4 ++++ scd/ccid-driver.c | 4 +++- 2 files changed, 7 insertions(+), 1 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Thu Jan 6 02:55:50 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Thu, 06 Jan 2011 02:55:50 +0100 Subject: [git] GnuPG - branch, ECC-INTEGRATION-2-1, created. gnupg-2.1.0beta1-32-ge0972d3 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, ECC-INTEGRATION-2-1 has been created at e0972d3d962548972872d889b362560e499340d1 (commit) - Log ----------------------------------------------------------------- commit e0972d3d962548972872d889b362560e499340d1 Author: Andrey Jivsov Date: Wed Jan 5 17:33:17 2011 -0800 Integrating http://code.google.com/p/gnupg-ecc/source/detail?r=15 . The following works: gpg2 --gen-key (ECC) gpg2 --list-keys gpg2 --list-packets ~/.gnupg/pubring.gpg gpg2 --list-packets ECDH doesn't work yet as the code must be re-written to adjust for gpg-agent refactoring. diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c index e6a14c4..3dba79e 100644 --- a/agent/cvt-openpgp.c +++ b/agent/cvt-openpgp.c @@ -27,6 +27,7 @@ #include "agent.h" #include "i18n.h" #include "cvt-openpgp.h" +#include "../include/cipher.h" /* for PUBKEY_ALGO_ECDSA, PUBKEY_ALGO_ECDH */ /* Helper to pass data via the callback to do_unprotect. */ @@ -49,7 +50,12 @@ struct try_do_unprotect_arg_s gcry_sexp_t *r_key; }; - +/* TODO: it is also in misc, which is not linked with the agent */ +static int +map_pk_openpgp_to_gcry (int algo) +{ + return (algo==PUBKEY_ALGO_ECDSA ? GCRY_PK_ECDSA : (algo==PUBKEY_ALGO_ECDH ? GCRY_PK_ECDH : algo)); +} /* Compute the keygrip from the public key and store it at GRIP. */ static gpg_error_t @@ -80,6 +86,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: + err = gcry_sexp_build (&s_pkey, NULL, + "(public-key(ecc(c%m)(q%m)))", pkey[0], pkey[1]); + break; + default: err = gpg_error (GPG_ERR_PUBKEY_ALGO); break; @@ -94,7 +106,9 @@ 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. */ + parameters into our s-expression based format. + pubkey_algo is a libgcrypt ID + */ static gpg_error_t convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey) { @@ -103,6 +117,8 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey) *r_key = NULL; + pubkey_algo = map_pk_openpgp_to_gcry( pubkey_algo ); + switch (pubkey_algo) { case GCRY_PK_DSA: @@ -128,6 +144,18 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey) skey[5]); 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: + 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]); + break; + default: err = gpg_error (GPG_ERR_PUBKEY_ALGO); break; @@ -202,6 +230,10 @@ do_unprotect (const char *passphrase, *r_key = NULL; + /* Unfortunately, the OpenPGP PK algorithm numbers need to be re-mapped for Libgcrypt + */ + pubkey_algo = map_pk_openpgp_to_gcry( pubkey_algo ); + /* Count the actual number of MPIs is in the array and set the remainder to NULL for easier processing later on. */ for (skeylen = 0; skey[skeylen]; skeylen++) @@ -219,9 +251,6 @@ do_unprotect (const char *passphrase, if (gcry_pk_test_algo (pubkey_algo)) { - /* The algorithm numbers are Libgcrypt numbers but fortunately - the OpenPGP algorithm numbers map one-to-one to the Libgcrypt - numbers. */ log_info (_("public key algorithm %d (%s) is not supported\n"), pubkey_algo, gcry_pk_algo_name (pubkey_algo)); return gpg_error (GPG_ERR_PUBKEY_ALGO); @@ -632,7 +661,7 @@ convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp, string = gcry_sexp_nth_string (list, 1); if (!string) goto bad_seckey; - pubkey_algo = gcry_pk_map_name (string); + pubkey_algo = gcry_pk_map_name (string); /* ligcrypt IDs */ xfree (string); if (gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &npkey) @@ -999,6 +1028,7 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, } algo = gcry_pk_map_name (name); + log_debug ( "convert to openpgp begin for algo=%s\n", name ); xfree (name); switch (algo) @@ -1007,7 +1037,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 = 6; elems = "pabgnqd"; break; + case GCRY_PK_ECDSA: algoname = "ecdsa"; npkey = 2; elems = "cqd"; break; + case GCRY_PK_ECDH: algoname = "ecdh"; npkey = 3; elems = "cqpd"; break; default: algoname = ""; npkey = 0; elems = NULL; break; } assert (!elems || strlen (elems) < DIM (array) ); @@ -1027,6 +1058,7 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, err = apply_protection (array, npkey, nskey, passphrase, GCRY_CIPHER_AES, protect_iv, sizeof protect_iv, 3, GCRY_MD_SHA1, salt, s2k_count); + ///log_debug ( "convert to openpgp: after applying protection, err = %d\n", err ); /* Turn it into the transfer key S-expression. Note that we always return a protected key. */ if (!err) @@ -1037,7 +1069,7 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, int format_args_buf_int[1]; void *format_args[10+2]; size_t n; - gcry_sexp_t tmpkey, tmpsexp; + gcry_sexp_t tmpkey, tmpsexp = NULL; snprintf (countbuf, sizeof countbuf, "%lu", s2k_count); @@ -1056,6 +1088,8 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, put_membuf_str (&mbuf, ")\n"); put_membuf (&mbuf, "", 1); + ///log_debug ( "convert to openpgp: calling gcry_sexp_build\n" ); + tmpkey = NULL; { char *format = get_membuf (&mbuf, NULL); @@ -1065,6 +1099,7 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, err = gcry_sexp_build_array (&tmpkey, NULL, format, format_args); xfree (format); } + ///log_debug ( "convert to openpgp: calling gcry_sexp_build before err=%d\n", err ); if (!err) err = gcry_sexp_build (&tmpsexp, NULL, "(openpgp-private-key\n" @@ -1077,6 +1112,7 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, (int)sizeof protect_iv, protect_iv, (int)sizeof salt, salt, countbuf); + ///log_debug ( "convert to openpgp: after gcry_sexp_build, err = %d\n", err ); gcry_sexp_release (tmpkey); if (!err) err = make_canon_sexp_pad (tmpsexp, 0, r_transferkey, r_transferkeylen); @@ -1085,6 +1121,8 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, for (i=0; i < DIM (array); i++) gcry_mpi_release (array[i]); + + log_debug ( "convert to openpgp end with err=%d\n", err ); return err; } diff --git a/agent/findkey.c b/agent/findkey.c index 91fb8c1..02e938e 100644 --- a/agent/findkey.c +++ b/agent/findkey.c @@ -726,6 +726,16 @@ key_parms_from_sexp (gcry_sexp_t s_key, gcry_sexp_t *r_list, algoname = "dsa"; elems = "pqgy"; } + else if (n==5 && !memcmp (name, "ecdsa", 5)) + { + algoname = "ecdsa"; + elems = "cq"; + } + else if (n==4 && !memcmp (name, "ecdh", 4)) + { + algoname = "ecdh"; + elems = "cqp"; + } else if (n==3 && !memcmp (name, "elg", 3)) { algoname = "elg"; diff --git a/agent/protect.c b/agent/protect.c index 795d062..d146653 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -52,6 +52,8 @@ static struct { { "rsa", "nedpqu", 2, 5 }, { "dsa", "pqgyx", 4, 4 }, { "elg", "pgyx", 3, 3 }, + { "ecdsa","cqd", 2, 2 }, + { "ecdh", "cqpd", 3, 3 }, { NULL } }; @@ -426,6 +428,9 @@ agent_protect (const unsigned char *plainkey, const char *passphrase, unsigned char *p; gcry_md_hd_t md; + if (opt.debug & DBG_CRYPTO_VALUE) + log_info ("Protecting key=%s, passphrase=%s\n", plainkey, passphrase); + /* Create an S-expression with the protected-at timestamp. */ memcpy (timestamp_exp, "(12:protected-at15:", 19); gnupg_get_isotime (timestamp_exp+19); @@ -454,37 +459,51 @@ agent_protect (const unsigned char *plainkey, const char *passphrase, for (infidx=0; protect_info[infidx].algo && !smatch (&s, n, protect_info[infidx].algo); infidx++) ; - if (!protect_info[infidx].algo) + if (!protect_info[infidx].algo) { + log_info ("Unsupported alg %d for protection\n", protect_info[infidx].algo); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); + } prot_begin = prot_end = NULL; for (i=0; (c=protect_info[infidx].parmlist[i]); i++) { if (i == protect_info[infidx].prot_from) prot_begin = s; - if (*s != '(') + if (*s != '(') { + log_info ("Unbalanced bracket in S-expression #1\n"); return gpg_error (GPG_ERR_INV_SEXP); + } depth++; s++; n = snext (&s); - if (!n) + if (!n) { + log_info ("Cannot get the length of S-expression field\n"); return gpg_error (GPG_ERR_INV_SEXP); - if (n != 1 || c != *s) + } + if (n != 1 || c != *s) { + log_info ("Invalid length in S-expression field\n"); return gpg_error (GPG_ERR_INV_SEXP); - s += n; + } + s += n; n = snext (&s); - if (!n) + if (!n) { + log_info ("Invalid fieled in S-expression field\n"); return gpg_error (GPG_ERR_INV_SEXP); + } s +=n; /* skip value */ - if (*s != ')') + if (*s != ')') { + log_info ("Unbalanced bracket in S-expression #2\n"); return gpg_error (GPG_ERR_INV_SEXP); + } depth--; if (i == protect_info[infidx].prot_to) prot_end = s; s++; } - if (*s != ')' || !prot_begin || !prot_end ) + if (*s != ')' || !prot_begin || !prot_end ) { + log_info ("Unbalanced bracket in S-expression #3\n"); return gpg_error (GPG_ERR_INV_SEXP); + } depth--; hash_end = s; s++; diff --git a/common/convert.c b/common/convert.c index aa3a3a8..0a0c46f 100644 --- a/common/convert.c +++ b/common/convert.c @@ -23,6 +23,7 @@ #include #include "util.h" +#include "gcrypt.h" #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A')) @@ -245,5 +246,31 @@ hex2str_alloc (const char *hexstring, size_t *r_count) return result; } +/* returns hex representation of the MPI; + * caller must free with xfree + * Returns NULL on error, never throws + */ +char *mpi2hex( gcry_mpi_t m ) { + size_t nbytes; + size_t nbytes2; + int rc; + byte *p; + + nbytes = (mpi_get_nbits ( m )+7)/8; + if( nbytes == 0 ) + return NULL; + p = xtrymalloc( nbytes*3+1 ); + if( p==NULL ) + return NULL; + rc = gcry_mpi_print (GCRYMPI_FMT_USG, p+2*nbytes+1, nbytes, &nbytes2, m); + if( rc ) { + xfree( p ); + return NULL; + } + bin2hex( p+2*nbytes+1, nbytes2, p ); + p[nbytes2*2] = '\0'; +//printf("%s:%d>>>> Created the string %s from %d bytes %02x %02x ..., MPI was %d bytes\n", __FILE__, __LINE__, p, nbytes2, p[2*nbytes+1], p[2*nbytes+2], nbytes); + return p; +} diff --git a/common/util.h b/common/util.h index 7c58b15..44a72d9 100644 --- a/common/util.h +++ b/common/util.h @@ -192,6 +192,7 @@ gpg_error_t get_pk_algo_from_canon_sexp (const unsigned char *keydata, int hex2bin (const char *string, void *buffer, size_t length); int hexcolon2bin (const char *string, void *buffer, size_t length); char *bin2hex (const void *buffer, size_t length, char *stringbuf); +char *mpi2hex (gcry_mpi_t m); char *bin2hexcolon (const void *buffer, size_t length, char *stringbuf); const char *hex2str (const char *hexstring, char *buffer, size_t bufsize, size_t *buflen); diff --git a/configure.ac b/configure.ac index 9757330..12545e2 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.10" # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [2.1.0]) +m4_define([my_version], [2.2.0]) m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([printf "%d" $(svn info 2>/dev/null \ @@ -43,7 +43,7 @@ development_version=no NEED_GPG_ERROR_VERSION=1.8 NEED_LIBGCRYPT_API=1 -NEED_LIBGCRYPT_VERSION=1.4.0 +NEED_LIBGCRYPT_VERSION=1.6.0 NEED_LIBASSUAN_API=2 NEED_LIBASSUAN_VERSION=2.0.0 @@ -1466,7 +1466,7 @@ AC_ARG_ENABLE(optimization, AC_HELP_STRING([--disable-optimization], [disable compiler optimization]), [if test $enableval = no ; then - CFLAGS=`echo $CFLAGS | sed s/-O[[1-9]]\ /-O0\ /g` + CFLAGS=`echo $CFLAGS | sed s%-O[[1-9]]%-O0\ %g` fi]) # diff --git a/dirmngr/Makefile.am b/dirmngr/Makefile.am index 5b1fe30..0285fc8 100644 --- a/dirmngr/Makefile.am +++ b/dirmngr/Makefile.am @@ -61,7 +61,7 @@ endif dirmngr_LDADD = $(libcommonpth) ../gl/libgnu.a $(DNSLIBS) $(LIBASSUAN_LIBS) \ $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(PTH_LIBS) $(LIBINTL) $(LIBICONV) if !USE_LDAPWRAPPER -dirmngr_LDADD += $(LDAPLIBS) +dirmngr_LDADD += $(LDAPLIBS) -llber endif dirmngr_LDFLAGS = $(extra_bin_ldflags) diff --git a/g10/Makefile.am b/g10/Makefile.am index c8fc482..b82fe07 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -72,7 +72,8 @@ common_source = \ plaintext.c \ sig-check.c \ keylist.c \ - pkglue.c pkglue.h + pkglue.c pkglue.h \ + ecdh.c gpg2_SOURCES = gpg.c \ server.c \ @@ -109,7 +110,8 @@ gpg2_SOURCES = gpg.c \ gpgv2_SOURCES = gpgv.c \ $(common_source) \ - verify.c + verify.c \ + verify-stubs.c #gpgd_SOURCES = gpgd.c \ # ks-proto.h \ diff --git a/g10/armor.c b/g10/armor.c index a6195fc..8cfd35c 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -1079,7 +1079,7 @@ armor_filter( void *opaque, int control, iobuf_writestr(a,afx->eol); if( !opt.no_version ) { - iobuf_writestr(a, "Version: GnuPG v" VERSION " (" + iobuf_writestr(a, "Version: GnuPG v" VERSION "-ecc (" PRINTABLE_OS_NAME ")" ); iobuf_writestr(a,afx->eol); } diff --git a/g10/build-packet.c b/g10/build-packet.c index 83d6c7a..3a2c206 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -178,6 +178,16 @@ mpi_write (iobuf_t out, gcry_mpi_t a) return rc; } +/* + * Write the name OID, encoded as an mpi, to OUT. The format of the content of the MPI is + * one byte LEN, following by LEN bytes that are DER representation of an ASN.1 OID. + * This is true for each of the 3 following functions. + */ +#define iobuf_name_oid_write iobuf_write_size_body_mpi +/* Write the value of KEK fields for ECDH. */ +#define ecdh_kek_params_write iobuf_write_size_body_mpi +/* Write the value of encrypted filed for ECDH. */ +#define ecdh_esk_write iobuf_write_size_body_mpi /**************** @@ -290,10 +300,24 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) } assert (npkey < nskey); - /* Writing the public parameters is easy. */ - for (i=0; i < npkey; i++ ) - if ((err = mpi_write (a, pk->pkey[i]))) - goto leave; + if( pk->pubkey_algo != PUBKEY_ALGO_ECDSA && pk->pubkey_algo != PUBKEY_ALGO_ECDH ) { + /* Writing the public parameters is easy, */ + for (i=0; i < npkey; i++ ) + if ((err = mpi_write (a, pk->pkey[i]))) + goto leave; + } + else { + /* ... except we do an adjustment for ECC OID and possibly KEK params for ECDH */ + if( (err=iobuf_name_oid_write(a, pk->pkey[0])) || /* DER of OID with preceeding length byte */ + (err = mpi_write (a, pk->pkey[1])) ) /* point Q, the public key */ + { + goto leave; + } + if( pk->pubkey_algo == PUBKEY_ALGO_ECDH && (err=ecdh_kek_params_write(a,pk->pkey[2]))) { /* one more public field for ECDH */ + goto leave; + } + /* followed by possibly protected private scalar */ + } if (pk->seckey_info) { @@ -458,8 +482,18 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) n = pubkey_get_nenc( enc->pubkey_algo ); if ( !n ) write_fake_data( a, enc->data[0] ); - for (i=0; i < n && !rc ; i++ ) - rc = mpi_write(a, enc->data[i] ); + + if( enc->pubkey_algo != PUBKEY_ALGO_ECDH ) { + for (i=0; i < n && !rc ; i++ ) + rc = mpi_write(a, enc->data[i] ); + } + else { + /* the second field persists as a LEN+field structure, even though it is + * stored for uniformity as an MPI internally */ + assert( n==2 ); + rc = mpi_write(a, enc->data[0] ); + if( !rc ) rc = ecdh_esk_write(a, enc->data[1] ); + } if (!rc) { diff --git a/g10/call-agent.c b/g10/call-agent.c index 9528e14..25f9a53 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -1744,6 +1744,7 @@ inq_ciphertext_cb (void *opaque, const char *line) gpg_error_t agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, gcry_sexp_t s_ciphertext, + const byte sk_fp[MAX_FINGERPRINT_LEN], unsigned char **r_buf, size_t *r_buflen) { gpg_error_t err; @@ -1751,6 +1752,8 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, membuf_t data; size_t n, len; char *p, *buf, *endp; + + /*TODO: use sk_fp */ if (!keygrip || strlen(keygrip) != 40 || !s_ciphertext || !r_buf || !r_buflen) return gpg_error (GPG_ERR_INV_VALUE); diff --git a/g10/call-agent.h b/g10/call-agent.h index e09c309..45e593b 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -168,6 +168,7 @@ gpg_error_t agent_pksign (ctrl_t ctrl, const char *cache_nonce, /* Decrypt a ciphertext. */ gpg_error_t agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, gcry_sexp_t s_ciphertext, + const byte sk_fp[MAX_FINGERPRINT_LEN], unsigned char **r_buf, size_t *r_buflen); /* Retrieve a key encryption key. */ diff --git a/g10/ecdh.c b/g10/ecdh.c new file mode 100644 index 0000000..6615b75 --- /dev/null +++ b/g10/ecdh.c @@ -0,0 +1,477 @@ +/* ecdh.c - ECDH public key operations used in public key glue code + * Copyright (C) 2000, 2003 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuPG is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include +#include +#include + +#include "gpg.h" +#include "util.h" +#include "pkglue.h" +#include "main.h" +#include "options.h" + +gcry_mpi_t +pk_ecdh_default_params_to_mpi( int qbits ) { + gpg_error_t err; + gcry_mpi_t result; + /* Defaults are the strongest possible choices. Performance is not an issue here, only interoperability. */ + byte kek_params[4] = { + 3 /*size of following field*/, + 1 /*fixed version for KDF+AESWRAP*/, + DIGEST_ALGO_SHA512 /* KEK MD */, + CIPHER_ALGO_AES256 /*KEK AESWRAP alg*/ + }; + int i; + + static const struct { + int qbits; + int openpgp_hash_id; + int openpgp_cipher_id; + } kek_params_table[] = { + { 256, DIGEST_ALGO_SHA256, CIPHER_ALGO_AES }, + { 384, DIGEST_ALGO_SHA384, CIPHER_ALGO_AES256 }, + { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 } // 528 is 521 rounded to the 8 bit boundary + }; + + for( i=0; i= qbits ) { + kek_params[2] = kek_params_table[i].openpgp_hash_id; + kek_params[3] = kek_params_table[i].openpgp_cipher_id; + break; + } + } + if( DBG_CIPHER ) + log_printhex ("ecdh kek params are", kek_params, sizeof(kek_params) ); + + err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, kek_params, sizeof(kek_params), NULL); + if (err) + log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); + + return result; +} + +/* returns allocated (binary) KEK parameters; the size is returned in sizeout. + * The caller must free returned value with xfree. + * Returns NULL on error + */ +byte * +pk_ecdh_default_params( int qbits, size_t *sizeout ) { + gpg_error_t err; + gcry_mpi_t result; + /* Defaults are the strongest possible choices. Performance is not an issue here, only interoperability. */ + byte kek_params[4] = { + 3 /*size of following field*/, + 1 /*fixed version for KDF+AESWRAP*/, + DIGEST_ALGO_SHA512 /* KEK MD */, + CIPHER_ALGO_AES256 /*KEK AESWRAP alg*/ + }; + int i; + + static const struct { + int qbits; + int openpgp_hash_id; + int openpgp_cipher_id; + } kek_params_table[] = { + { 256, DIGEST_ALGO_SHA256, CIPHER_ALGO_AES }, + { 384, DIGEST_ALGO_SHA384, CIPHER_ALGO_AES256 }, + { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 } // 528 is 521 rounded to the 8 bit boundary + }; + + byte *p; + + *sizeout = 0; + + for( i=0; i= qbits ) { + kek_params[2] = kek_params_table[i].openpgp_hash_id; + kek_params[3] = kek_params_table[i].openpgp_cipher_id; + break; + } + } + if( DBG_CIPHER ) + log_printhex ("ecdh kek params are", kek_params, sizeof(kek_params) ); + + p = xtrymalloc( sizeof(kek_params) ); + if( p == NULL ) + return NULL; + memcpy( p, kek_params, sizeof(kek_params) ); + *sizeout = sizeof(kek_params); + return p; +} + +/* Encrypts/decrypts 'data' with a key derived from shared_mpi ECC point using FIPS SP 800-56A compliant method, which is + * key derivation + key wrapping. The direction is determined by the first parameter (is_encrypt=1 --> this is encryption). + * The result is returned in out as a size+value MPI. + * TODO: memory leaks (x_secret). + */ +static int +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 *out) +{ + byte *secret_x; + int secret_x_size; + byte kdf_params[256]; + int kdf_params_size=0; + int nbits; + int kdf_hash_algo; + int kdf_encr_algo; + int rc; + + *out = NULL; + + nbits = pubkey_nbits( PUBKEY_ALGO_ECDH, pkey ); + + { + size_t nbytes; + /* extract x component of the shared point: this is the actual shared secret */ + nbytes = (mpi_get_nbits (pkey[1] /* public point */)+7)/8; + secret_x = xmalloc_secure( nbytes ); + rc = gcry_mpi_print (GCRYMPI_FMT_USG, secret_x, nbytes, &nbytes, shared_mpi); + if( rc ) { + xfree( secret_x ); + log_error ("ec ephemeral export of shared point failed: %s\n", gpg_strerror (rc) ); + return rc; + } + 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 ); + } + + /*** We have now the shared secret bytes in secret_x ***/ + + /* At this point we are done with PK encryption and the rest of the function uses symmetric + * key encryption techniques to protect the input 'data'. The following two sections will + * simply replace current secret_x with a value derived from it. This will become a KEK. + */ + { + IOBUF obuf = iobuf_temp(); + rc = iobuf_write_size_body_mpi ( obuf, pkey[2] ); /* KEK params */ + + kdf_params_size = iobuf_temp_to_buffer( obuf, kdf_params, sizeof(kdf_params) ); + + if( DBG_CIPHER ) + log_printhex ("ecdh KDF public key params are:", kdf_params, kdf_params_size ); + + if( kdf_params_size != 4 || kdf_params[0] != 3 || kdf_params[1] != 1 ) /* expect 4 bytes 03 01 hash_alg symm_alg */ + return GPG_ERR_BAD_PUBKEY; + + kdf_hash_algo = kdf_params[2]; + kdf_encr_algo = kdf_params[3]; + + if( DBG_CIPHER ) + log_debug ("ecdh KDF algorithms %s+%s with aeswrap\n", gcry_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 ) + return GPG_ERR_BAD_PUBKEY; + if( kdf_encr_algo != GCRY_CIPHER_AES128 && kdf_encr_algo != GCRY_CIPHER_AES192 && kdf_encr_algo != GCRY_CIPHER_AES256 ) + return GPG_ERR_BAD_PUBKEY; + } + + /* build kdf_params */ + { + IOBUF obuf; + + obuf = iobuf_temp(); + /* variable-length field 1, curve name OID */ + rc = iobuf_write_size_body_mpi ( obuf, pkey[0] ); + /* fixed-length field 2 */ + iobuf_put (obuf, PUBKEY_ALGO_ECDH); + /* variable-length field 3, KDF params */ + rc = (rc ? rc : iobuf_write_size_body_mpi ( obuf, pkey[2] )); + /* fixed-length field 4 */ + iobuf_write (obuf, "Anonymous Sender ", 20); + /* fixed-length field 5, recipient fp */ + iobuf_write (obuf, pk_fp, 20); + + kdf_params_size = iobuf_temp_to_buffer( obuf, kdf_params, sizeof(kdf_params) ); + iobuf_close( obuf ); + if( rc ) { + return rc; + } + if( DBG_CIPHER ) + log_printhex ("ecdh KDF message params are:", kdf_params, kdf_params_size ); + } + + /* Derive a KEK (key wrapping key) using kdf_params and secret_x. */ + { + gcry_md_hd_t h; + int old_size; + + rc = gcry_md_open (&h, kdf_hash_algo, 0); + if(rc) + log_bug ("gcry_md_open failed for algo %d: %s", + kdf_hash_algo, gpg_strerror (gcry_error(rc))); + 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_final (h); + + assert( gcry_md_get_algo_dlen (kdf_hash_algo) >= 32 ); + + memcpy (secret_x, gcry_md_read (h, kdf_hash_algo), gcry_md_get_algo_dlen (kdf_hash_algo)); + gcry_md_close (h); + + old_size = secret_x_size; + assert( old_size >= gcry_cipher_get_algo_keylen( kdf_encr_algo ) ); + secret_x_size = gcry_cipher_get_algo_keylen( kdf_encr_algo ); + assert( secret_x_size <= gcry_md_get_algo_dlen (kdf_hash_algo) ); + + memset( secret_x+secret_x_size, old_size-secret_x_size, 0 ); /* we could have allocated more, so clean the tail before returning */ + 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; + size_t nbytes; + + byte *data_buf; + int data_buf_size; + + gcry_mpi_t result; + + rc = gcry_cipher_open (&hd, kdf_encr_algo, GCRY_CIPHER_MODE_AESWRAP, 0); + if (rc) + { + log_error( "ecdh failed to initialize AESWRAP: %s\n", gpg_strerror (rc)); + return rc; + } + + rc = gcry_cipher_setkey (hd, secret_x, secret_x_size); + xfree( secret_x ); + if (rc) + { + gcry_cipher_close (hd); + log_error("ecdh failed in gcry_cipher_setkey: %s\n", gpg_strerror (rc)); + return rc; + } + + data_buf_size = (gcry_mpi_get_nbits(data)+7)/8; + assert( (data_buf_size & 7) == (is_encrypt ? 0 : 1) ); + + data_buf = xmalloc_secure( 1 + 2*data_buf_size + 8 ); + if( !data_buf ) { + gcry_cipher_close (hd); + return GPG_ERR_ENOMEM; + } + + 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 */ + rc = gcry_mpi_print (GCRYMPI_FMT_USG, in, data_buf_size, &nbytes, data/*in*/); + if( rc ) { + log_error("ecdh failed to export DEK: %s\n", gpg_strerror (rc)); + gcry_cipher_close (hd); + xfree( data_buf ); + return rc; + } + + if( DBG_CIPHER ) + log_printhex ("ecdh encrypting :", in, data_buf_size ); + + rc = gcry_cipher_encrypt (hd, data_buf+1, data_buf_size+8, in, data_buf_size); + memset( in, 0, data_buf_size); + gcry_cipher_close (hd); + if(rc) + { + log_error("ecdh failed in gcry_cipher_encrypt: %s\n", gpg_strerror (rc)); + xfree( data_buf ); + return rc; + } + data_buf[0] = data_buf_size+8; + + if( DBG_CIPHER ) + log_printhex ("ecdh encrypted to:", data_buf+1, data_buf[0] ); + + rc = gcry_mpi_scan ( &result, GCRYMPI_FMT_USG, data_buf, 1+data_buf[0], NULL); /* (byte)size + aeswrap of DEK */ + xfree( data_buf ); + if(rc) + { + log_error("ecdh failed to create an MPI: %s\n", gpg_strerror (rc)); + return rc; + } + + *out = result; + } + else { + byte *in; + + rc = gcry_mpi_print (GCRYMPI_FMT_USG, data_buf, data_buf_size, &nbytes, data/*in*/); + if( nbytes != data_buf_size || data_buf[0] != data_buf_size-1 ) { + log_error("ecdh inconsistent size\n"); + xfree( data_buf ); + return GPG_ERR_BAD_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 ); + + rc = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1, data_buf_size ); + gcry_cipher_close (hd); + if(rc) + { + log_error("ecdh failed in gcry_cipher_decrypt: %s\n", gpg_strerror (rc)); + xfree( data_buf ); + return rc; + } + + 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 ) { + // log_error("ecdh failed at decryption: invalid padding. %02x > 8\n", in[data_buf_size-1] ); + // return GPG_ERR_BAD_KEY; + //} + + rc = gcry_mpi_scan ( &result, GCRYMPI_FMT_USG, in, data_buf_size, NULL); + xfree( data_buf ); + if(rc) + { + log_error("ecdh failed to create a plain text MPI: %s\n", gpg_strerror (rc)); + return rc; + } + + *out = result; + } + } + + return rc; +} + +/* Perform ECDH encryption, which involves ECDH key generation. + */ +int +pk_ecdh_encrypt (gcry_mpi_t * resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t * pkey) +{ + gcry_sexp_t s_ciph, s_data, s_pkey; + + PKT_public_key *pk_eph; + int nbits; + int rc; + + nbits = pubkey_nbits( PUBKEY_ALGO_ECDH, pkey ); + + /*** Generate an ephemeral key ***/ + + rc = pk_ecc_keypair_gen( &pk_eph, PUBKEY_ALGO_ECDH, KEYGEN_FLAG_TRANSIENT_KEY | KEYGEN_FLAG_NO_PROTECTION /*this is ephemeral*/, "", nbits ); + if( rc ) + return rc; + if( DBG_CIPHER ) { + unsigned char *buffer; + if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, pk_eph->pkey[1])) + BUG (); + log_debug("ephemeral key MPI #0: %s\n", buffer); + gcry_free( buffer ); + } + free_public_key (pk_eph); + + /*** Done with ephemeral key generation. + * Now use ephemeral secret to get the shared secret. ***/ + + rc = gcry_sexp_build (&s_pkey, NULL, + "(public-key(ecdh(c%m)(q%m)(p%m)))", pkey[0], pkey[1], pkey[2]); + if (rc) + BUG (); + + /* put the data into a simple list */ + if (gcry_sexp_build (&s_data, NULL, "%m", pk_eph->pkey[3])) /* ephemeral scalar goes as data */ + BUG (); + + /* pass it to libgcrypt */ + rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey); + gcry_sexp_release (s_data); + gcry_sexp_release (s_pkey); + if (rc) + return rc; + + /* finally, perform encryption */ + + { + gcry_mpi_t shared = mpi_from_sexp (s_ciph, "a"); /* ... and get the shared point */ + gcry_sexp_release (s_ciph); + resarr[0] = pk_eph->pkey[1]; /* ephemeral public key */ + + if( DBG_CIPHER ) { + unsigned char *buffer; + if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, resarr[0])) + BUG (); + log_debug("ephemeral key MPI: %s\n", buffer); + gcry_free( buffer ); + } + + rc = pk_ecdh_encrypt_with_shared_point ( 1 /*=encrypton*/, shared, pk_fp, data, pkey, resarr+1 ); + mpi_release( shared ); + } + + return rc; +} + +/* Perform ECDH decryption. + */ +int +pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t *data, gcry_mpi_t * skey) { + gcry_sexp_t s_skey, s_data, s_ciph; + int rc; + + if (!data[0] || !data[1]) + return gpg_error (GPG_ERR_BAD_MPI); + + rc = gcry_sexp_build (&s_skey, NULL, + "(public-key(ecdh(c%m)(q%m)(p%m)))", + skey[0]/*curve*/, data[0]/*ephemeral key*/, skey[2]/*KDF params*/); + if (rc) + BUG (); + + /* put the data into a simple list */ + if (gcry_sexp_build (&s_data, NULL, "%m", skey[3])) /* static private key (scalar) goes as data */ + BUG (); + + rc = gcry_pk_encrypt (&s_ciph, s_data, s_skey); /* encrypting ephemeral key with our private scalar yields the shared point */ + gcry_sexp_release (s_skey); + gcry_sexp_release (s_data); + if (rc) + return rc; + + { + gcry_mpi_t shared = mpi_from_sexp (s_ciph, "a"); /* get the shared point */ + gcry_sexp_release (s_ciph); + rc = pk_ecdh_encrypt_with_shared_point ( 0 /*=decryption*/, shared, sk_fp, data[1]/*encr data as an MPI*/, skey, result ); + mpi_release( shared ); + } + + return rc; +} + + diff --git a/g10/encrypt.c b/g10/encrypt.c index 55f9b27..3c16309 100644 --- a/g10/encrypt.c +++ b/g10/encrypt.c @@ -876,7 +876,9 @@ write_pubkey_enc_from_list (PK_LIST pk_list, DEK *dek, iobuf_t out) for ( ; pk_list; pk_list = pk_list->next ) { gcry_mpi_t frame; - + byte fp[MAX_FINGERPRINT_LEN]; + size_t fpn; + pk = pk_list->pk; print_pubkey_algo_note ( pk->pubkey_algo ); @@ -892,6 +894,9 @@ write_pubkey_enc_from_list (PK_LIST pk_list, DEK *dek, iobuf_t out) compliance_failure(); } + fingerprint_from_pk( pk, fp, &fpn ); + assert( fpn == 20 ); + /* Okay, what's going on: We have the session key somewhere in * the structure DEK and want to encode this session key in an * integer value of n bits. pubkey_nbits gives us the number of @@ -904,9 +909,9 @@ write_pubkey_enc_from_list (PK_LIST pk_list, DEK *dek, iobuf_t out) * for Elgamal). We don't need frame anymore because we have * everything now in enc->data which is the passed to * build_packet(). */ - frame = encode_session_key (dek, + frame = encode_session_key (pk->pubkey_algo, dek, pubkey_nbits (pk->pubkey_algo, pk->pkey)); - rc = pk_encrypt (pk->pubkey_algo, enc->data, frame, pk->pkey); + rc = pk_encrypt (pk->pubkey_algo, enc->data, frame, fp, pk->pkey); gcry_mpi_release (frame); if (rc) log_error ("pubkey_encrypt failed: %s\n", gpg_strerror (rc) ); diff --git a/g10/export.c b/g10/export.c index 91c6a73..82d9751 100644 --- a/g10/export.c +++ b/g10/export.c @@ -1161,6 +1161,18 @@ build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent) /* iobuf_put (out,')'); iobuf_put (out,'\n'); */ /* (*indent)--; */ /* } */ +/* + else if (sk->pubkey_algo == PUBKEY_ALGO_ECDSA && !sk->is_protected) + { + write_sexp_line (out, indent, "(ecdsa\n"); + (*indent)++; + write_sexp_keyparm (out, indent, "c", sk->skey[0]); iobuf_put (out,'\n'); + write_sexp_keyparm (out, indent, "q", sk->skey[6]); iobuf_put (out,'\n'); + write_sexp_keyparm (out, indent, "d", sk->skey[7]); + 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"); */ diff --git a/g10/getkey.c b/g10/getkey.c index f114920..65f5829 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -138,7 +138,10 @@ cache_public_key (PKT_public_key * pk) return; if (is_ELGAMAL (pk->pubkey_algo) - || pk->pubkey_algo == PUBKEY_ALGO_DSA || is_RSA (pk->pubkey_algo)) + || pk->pubkey_algo == PUBKEY_ALGO_DSA + || pk->pubkey_algo == PUBKEY_ALGO_ECDSA + || pk->pubkey_algo == PUBKEY_ALGO_ECDH + || is_RSA (pk->pubkey_algo)) { keyid_from_pk (pk, keyid); } diff --git a/g10/gpg.c b/g10/gpg.c index 4a17b29..23b1934 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -813,7 +813,7 @@ my_strusage( int level ) const char *p; switch( level ) { - case 11: p = "gpg (GnuPG)"; + case 11: p = "gpg (GnuPG) ecc"; break; case 13: p = VERSION; break; case 17: p = PRINTABLE_OS_NAME; break; @@ -857,7 +857,7 @@ my_strusage( int level ) case 34: if (!pubkeys) pubkeys = build_list (_("Pubkey: "), 0, - gcry_pk_algo_name, + openpgp_pk_algo_name, openpgp_pk_test_algo ); p = pubkeys; break; diff --git a/g10/keygen.c b/g10/keygen.c index ec7e7e7..f7f1526 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -42,6 +42,8 @@ #include "i18n.h" #include "keyserver-internal.h" #include "call-agent.h" +#include "pkglue.h" +#include "gcrypt.h" /* The default algorithms. If you change them remember to change them also in gpg.c:gpgconf_list. You should also check that the value @@ -49,10 +51,6 @@ #define DEFAULT_STD_ALGO GCRY_PK_RSA #define DEFAULT_STD_KEYSIZE 2048 -#define KEYGEN_FLAG_NO_PROTECTION 1 -#define KEYGEN_FLAG_TRANSIENT_KEY 2 - - #define MAX_PREFS 30 enum para_name { @@ -1130,17 +1128,15 @@ key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, } - -/* Common code for the key generation fucntion gen_xxx. */ static int -common_gen (const char *keyparms, int algo, const char *algoelem, - kbnode_t pub_root, u32 timestamp, u32 expireval, int is_subkey, - int keygen_flags, char **cache_nonce_addr) +common_key_gen (const char *keyparms, int algo, const char *algoelem, + int keygen_flags, char **cache_nonce_addr, PKT_public_key **pk_out) { int err; - PACKET *pkt; PKT_public_key *pk; gcry_sexp_t s_key; + + *pk_out = NULL; err = agent_genkey (NULL, cache_nonce_addr, keyparms, !!(keygen_flags & KEYGEN_FLAG_NO_PROTECTION), &s_key); @@ -1158,10 +1154,7 @@ common_gen (const char *keyparms, int algo, const char *algoelem, return err; } - pk->timestamp = timestamp; pk->version = 4; - if (expireval) - pk->expiredate = pk->timestamp + expireval; pk->pubkey_algo = algo; err = key_from_sexp (pk->pkey, s_key, "public-key", algoelem); @@ -1174,21 +1167,45 @@ common_gen (const char *keyparms, int algo, const char *algoelem, } gcry_sexp_release (s_key); - pkt = xtrycalloc (1, sizeof *pkt); - if (!pkt) - { - err = gpg_error_from_syserror (); - free_public_key (pk); - return err; - } - - pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY; - pkt->pkt.public_key = pk; - add_kbnode (pub_root, new_kbnode (pkt)); + *pk_out = pk; return 0; } +/* Common code for the key generation fucntion gen_xxx. */ +static int +common_gen (const char *keyparms, int algo, const char *algoelem, + kbnode_t pub_root, u32 timestamp, u32 expireval, int is_subkey, + int keygen_flags, char **cache_nonce_addr) +{ + PKT_public_key *pk; + int err; + + err = common_key_gen( keyparms, algo, algoelem, keygen_flags, cache_nonce_addr, &pk ); + + if( !err ) { + PACKET *pkt; + + pk->timestamp = timestamp; + if (expireval) + pk->expiredate = pk->timestamp + expireval; + + pkt = xtrycalloc (1, sizeof *pkt); + if (!pkt) + { + err = gpg_error_from_syserror (); + free_public_key (pk); + return err; + } + + pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY; + pkt->pkt.public_key = pk; + + add_kbnode (pub_root, new_kbnode (pkt)); + } + + return err; +} /* * Generate an Elgamal key. @@ -1326,6 +1343,186 @@ gen_dsa (unsigned int nbits, KBNODE pub_root, return err; } +/* Returns allocated ECC key generation S-explression + call gcry_sexp_release ( out ) to free it. + */ +static int +delme__pk_ecc_build_sexp( int qbits, int algo, int is_long_term, gcry_sexp_t *out ) { + gcry_mpi_t kek_params; + char *kek_params_s; + int rc; + + if( is_long_term && algo == PUBKEY_ALGO_ECDH ) + kek_params = pk_ecdh_default_params_to_mpi( qbits ); + else + kek_params = NULL; + + if( kek_params ) { + kek_params_s = mpi2hex( kek_params ); + mpi_release( kek_params ); + } + + rc = gcry_sexp_build (out, NULL, + algo == PUBKEY_ALGO_ECDSA ? + "(genkey(ecdsa(nbits %d)(qbits %d)))" : + "(genkey(ecdh(nbits %d)(qbits %d)(transient-key %d)(kek-params %s)))", + (int)qbits, (int)qbits, (int)(is_long_term==0), kek_params_s); + xfree( kek_params_s ); + if (rc) { + log_debug("ec gen gcry_sexp_build failed: %s\n", gpg_strerror (rc)); + return rc; + } + return 0; +} + +static char * +pk_ecc_build_key_params( int qbits, int algo, int transient ) { + byte *kek_params = NULL; + size_t kek_params_size; + char nbitsstr[35]; + char qbitsstr[35]; + char *keyparms; + int n; + + /* KEK parameters are only needed for long term key generation */ + if( !transient && algo == PUBKEY_ALGO_ECDH ) + kek_params = pk_ecdh_default_params( qbits, &kek_params_size ); + else + kek_params = NULL; + + snprintf (nbitsstr, sizeof nbitsstr, "%u", qbits); + snprintf (qbitsstr, sizeof qbitsstr, "%u", qbits); + if( algo == PUBKEY_ALGO_ECDSA || kek_params == NULL ) + keyparms = xtryasprintf ( + "(genkey(%s(nbits %zu:%s)(qbits %zu:%s)(transient-key 1:%d)))", + algo == PUBKEY_ALGO_ECDSA ? "ecdsa" : "ecdh", + strlen (nbitsstr), nbitsstr, + strlen (qbitsstr), qbitsstr, + transient ); + else { + assert( kek_params != NULL ); + keyparms = xtryasprintf ( + "(genkey(ecdh(nbits %zu:%s)(qbits %zu:%s)(transient-key 1:%d)(kek-params %u:", + strlen (nbitsstr), nbitsstr, + strlen (qbitsstr), qbitsstr, + transient, + (unsigned)kek_params_size ); + if( keyparms != NULL ) { + n = strlen(keyparms); + keyparms = xtryrealloc( keyparms, n + kek_params_size + 4 ); + } + if( keyparms == NULL ) { + xfree( kek_params ); + return NULL; + } + memcpy( keyparms+n, kek_params, kek_params_size ); + xfree( kek_params ); + memcpy( keyparms+n+kek_params_size, ")))", 4 ); + } + return keyparms; +} + +/* This common function is used in this file and also to generate ephemeral keys for ECDH. + * Caller must call free_public_key and free_secret_key */ +int +pk_ecc_keypair_gen( PKT_public_key **pk_out, int algo, int keygen_flags, char **cache_nonce_addr, unsigned nbits) { + int err; + unsigned int qbits; + char *keyparms; + // PUBKEY_ALGO_ECDH, PUBKEY_ALGO_ECDSA + static const char * const ec_pub_params[2] = { "cqp", "cq" }; + //static const char * const ec_priv_params[2] = { "cqpd", "cqd" }; + + assert( algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH ); + assert( PUBKEY_ALGO_ECDSA == PUBKEY_ALGO_ECDH + 1 ); + + *pk_out = NULL; + + if( pubkey_get_npkey (PUBKEY_ALGO_ECDSA) != 2 || pubkey_get_nskey (PUBKEY_ALGO_ECDSA) != 3 || + pubkey_get_npkey (PUBKEY_ALGO_ECDH) != 3 || pubkey_get_nskey (PUBKEY_ALGO_ECDH) != 4 ) + { + log_info(_("incompatible version of gcrypt library (expect named curve logic for ECC)\n") ); + return GPG_ERR_EPROGMISMATCH; + } + + if ( nbits != 256 && nbits != 384 && nbits != 521 ) + { + log_info(_("keysize invalid; using 256 bits instead of passed in %d\n"), nbits ); + } + + /* + Figure out a q size based on the key size. See gen_dsa for more details. + Due to 8-bit rounding we may get 528 here instead of 521 + */ + nbits = qbits = (nbits < 521 ? nbits : 521 ); + + keyparms = pk_ecc_build_key_params(qbits, algo, !!((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY) && (keygen_flags & KEYGEN_FLAG_NO_PROTECTION)) ); + if (!keyparms) { + err = gpg_error_from_syserror (); + log_error ("ec pk_ecc_build_key_params failed: %s\n", gpg_strerror (err) ); + } + else + { + err = common_key_gen (keyparms, algo, ec_pub_params[algo-PUBKEY_ALGO_ECDH], + keygen_flags, cache_nonce_addr, pk_out); + xfree (keyparms); + } + +#if 0 + /* always allocase seckey_info for EC keys. TODO: is this needed? */ + if( *pk_out ) { + struct seckey_info *ski; + + (*pk_out)->seckey_info = ski = xtrycalloc (1, sizeof *ski); + if (!(*pk_out)->seckey_info) { + free_public_key(*pk_out); + *pk_out = NULL; + return gpg_error_from_syserror (); + } + + ski->is_protected = 0; + ski->algo = 0; + } +#endif + + return err; +} + + +/**************** + * Generate an ECC OpenPGP key + */ +static gpg_error_t +gen_ecc (int algo, unsigned int nbits, KBNODE pub_root, + u32 timestamp, u32 expireval, int is_subkey, + int keygen_flags, char **cache_nonce_addr) +{ + int rc; + PACKET *pkt; + PKT_public_key *pk; + + rc = pk_ecc_keypair_gen( &pk, algo, keygen_flags, cache_nonce_addr, nbits ); + if( rc ) + return rc; + + /* the rest is very similar to common_gen */ + + pk->timestamp = timestamp; + if (expireval) + pk->expiredate = pk->timestamp + expireval; + + //assert( pk->seckey_info != NULL ); + /// TODO: the new agent-based model doesn't return private portion here (the pkey array is allocated, but private MPIs are NULL, so this will cause a crash... ) + ///pk->seckey_info->csum = checksum_mpi ( pk->pkey[algo==PUBKEY_ALGO_ECDSA ? 2 : 3] ); /* corresponds to 'd' in 'cqd' or 'cqpd' */ + + pkt = xmalloc_clear(sizeof *pkt); + pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY; + pkt->pkt.public_key = pk; + add_kbnode(pub_root, new_kbnode( pkt )); + + return 0; +} + /* * Generate an RSA key. @@ -1557,6 +1754,8 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage) tty_printf (_(" (%d) RSA (set your own capabilities)\n"), 8 ); } + tty_printf (_(" (%d) ECDSA and ECDH\n"), 9 ); + for(;;) { *r_usage = 0; @@ -1613,6 +1812,12 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage) *r_usage = ask_key_flags (algo, addmode); break; } + else if (algo == 9) + { + algo = PUBKEY_ALGO_ECDSA; + *r_subkey_algo = PUBKEY_ALGO_ECDH; + break; + } else tty_printf (_("Invalid selection.\n")); } @@ -1657,13 +1862,20 @@ ask_keysize (int algo, unsigned int primary_keysize) max=3072; break; + case PUBKEY_ALGO_ECDSA: + case PUBKEY_ALGO_ECDH: + min=256; + def=256; + max=521; + break; + case PUBKEY_ALGO_RSA: min=1024; break; } tty_printf(_("%s keys may be between %u and %u bits long.\n"), - gcry_pk_algo_name (algo), min, max); + openpgp_pk_algo_name (algo), min, max); for(;;) { @@ -1682,7 +1894,7 @@ ask_keysize (int algo, unsigned int primary_keysize) if(nbitsmax) tty_printf(_("%s keysizes must be in the range %u-%u\n"), - gcry_pk_algo_name (algo), min, max); + openpgp_pk_algo_name (algo), min, max); else break; } @@ -1692,10 +1904,18 @@ ask_keysize (int algo, unsigned int primary_keysize) leave: if( algo == PUBKEY_ALGO_DSA && (nbits % 64) ) { - nbits = ((nbits + 63) / 64) * 64; - if (!autocomp) - tty_printf(_("rounded up to %u bits\n"), nbits ); + if( !(algo == PUBKEY_ALGO_ECDSA && nbits==521) ) { + nbits = ((nbits + 63) / 64) * 64; + if (!autocomp) + tty_printf(_("rounded up to %u bits\n"), nbits ); + } } + else if( algo == PUBKEY_ALGO_ECDH || algo == PUBKEY_ALGO_ECDSA ) { + if( nbits != 256 && nbits != 384 && nbits != 521 ) { + nbits = min; + tty_printf(_("unsupported ECDH value, corrected to the minimum %u bits\n"), nbits ); + } + } else if( (nbits % 32) ) { nbits = ((nbits + 31) / 32) * 32; @@ -2185,6 +2405,9 @@ do_create (int algo, unsigned int nbits, KBNODE pub_root, else if (algo == PUBKEY_ALGO_DSA) err = gen_dsa (nbits, pub_root, timestamp, expiredate, is_subkey, keygen_flags, cache_nonce_addr); + else if( algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH ) + err = gen_ecc (algo, nbits, pub_root, timestamp, expiredate, is_subkey, + keygen_flags, cache_nonce_addr); else if (algo == PUBKEY_ALGO_RSA) err = gen_rsa (algo, nbits, pub_root, timestamp, expiredate, is_subkey, keygen_flags, cache_nonce_addr); diff --git a/g10/keyid.c b/g10/keyid.c index 62ce036..2a9bd19 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -57,6 +57,8 @@ pubkey_letter( int algo ) case PUBKEY_ALGO_ELGAMAL_E: return 'g'; case PUBKEY_ALGO_ELGAMAL: return 'G' ; case PUBKEY_ALGO_DSA: return 'D' ; + case PUBKEY_ALGO_ECDSA: return 'E' ; // ECC DSA (sign only) + case PUBKEY_ALGO_ECDH: return 'e' ; // ECC DH (encrypt only) default: return '?'; } } @@ -74,6 +76,8 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) unsigned int nbits; size_t nbytes; int npkey = pubkey_get_npkey (pk->pubkey_algo); + /* name OID, MPI of public point, [for ECDH only: KEK params] */ + enum gcry_mpi_format ecc_pub_format[3] = {GCRYMPI_FMT_USG, GCRYMPI_FMT_PGP, GCRYMPI_FMT_USG}; /* Two extra bytes for the expiration date in v3 */ if(pk->version<4) @@ -90,11 +94,13 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) { for(i=0; i < npkey; i++ ) { - if (gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, pk->pkey[i])) + const enum gcry_mpi_format fmt = + ((pk->pubkey_algo==PUBKEY_ALGO_ECDSA || pk->pubkey_algo==PUBKEY_ALGO_ECDH) ? ecc_pub_format[i] : GCRYMPI_FMT_PGP); + + if (gcry_mpi_print (fmt, 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])) + if (gcry_mpi_print (fmt, pp[i], nbytes, &nbytes, pk->pkey[i])) BUG (); nn[i] = nbytes; n += nn[i]; @@ -712,6 +718,20 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array) pk->pkey[0], pk->pkey[1]); break; + case PUBKEY_ALGO_ECDSA: + case PUBKEY_ALGO_ECDH: + err = gcry_sexp_build (&s_pkey, NULL, + "(public-key(ecc(c%m)(q%m)))", + pk->pkey[0], pk->pkey[1]); + break; +/* + case PUBKEY_ALGO_ECDH: + err = gcry_sexp_build (&s_pkey, NULL, + "(public-key(ecdh(c%m)(q%m)(p%m)))", + pk->pkey[0], pk->pkey[1], pk->pkey[2]); + break; +*/ + default: err = gpg_error (GPG_ERR_PUBKEY_ALGO); break; diff --git a/g10/main.h b/g10/main.h index b673cf5..e336e5c 100644 --- a/g10/main.h +++ b/g10/main.h @@ -93,11 +93,12 @@ int map_cipher_openpgp_to_gcry (int algo); int openpgp_cipher_blocklen (int algo); int openpgp_cipher_test_algo( int algo ); const char *openpgp_cipher_algo_name (int algo); +int map_pk_openpgp_to_gcry (int algo); int openpgp_pk_test_algo( int algo ); int openpgp_pk_test_algo2 ( int algo, unsigned int use ); int openpgp_pk_algo_usage ( int algo ); -const char *openpgp_pk_algo_name (int algo); int openpgp_md_test_algo( int algo ); +const char *openpgp_pk_algo_name (int algo); const char *openpgp_md_algo_name (int algo); #ifdef USE_IDEA @@ -157,6 +158,10 @@ int pubkey_get_nsig( int algo ); int pubkey_get_nenc( int algo ); unsigned int pubkey_nbits( int algo, gcry_mpi_t *pkey ); int mpi_print (estream_t stream, gcry_mpi_t a, int mode); +int iobuf_write_size_body_mpi (iobuf_t out, gcry_mpi_t a); +int iobuf_read_size_body(iobuf_t inp, byte *body, int body_max_size, int pktlen, gcry_mpi_t *out); + +int ecdsa_qbits_from_Q( int qbits ); /*-- status.c --*/ void set_status_fd ( int fd ); @@ -251,6 +256,10 @@ gpg_error_t generate_card_subkeypair (kbnode_t pub_keyblock, int save_unprotected_key_to_card (PKT_public_key *sk, int keyno); #endif +#define KEYGEN_FLAG_NO_PROTECTION 1 +#define KEYGEN_FLAG_TRANSIENT_KEY 2 +int pk_ecc_keypair_gen( PKT_public_key **pk_out, int algo, int keygen_flags, char **cache_nonce_addr, unsigned nbits); + /*-- openfile.c --*/ int overwrite_filep( const char *fname ); char *make_outfile_name( const char *iname ); @@ -261,7 +270,7 @@ void try_make_homedir( const char *fname ); /*-- seskey.c --*/ void make_session_key( DEK *dek ); -gcry_mpi_t encode_session_key( DEK *dek, unsigned nbits ); +gcry_mpi_t encode_session_key( int openpgp_pk_algo, DEK *dek, unsigned nbits ); gcry_mpi_t encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo ); diff --git a/g10/mainproc.c b/g10/mainproc.c index 72cefce..dcbc4b4 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -384,6 +384,8 @@ proc_pubkey_enc( CTX c, PACKET *pkt ) } else if( is_ELGAMAL(enc->pubkey_algo) || enc->pubkey_algo == PUBKEY_ALGO_DSA + || enc->pubkey_algo == PUBKEY_ALGO_ECDSA + || enc->pubkey_algo == PUBKEY_ALGO_ECDH || is_RSA(enc->pubkey_algo) || enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL) { /* Note that we also allow type 20 Elgamal keys for decryption. @@ -450,7 +452,7 @@ print_pkenc_list( struct kidlist_item *list, int failed ) if ( !failed && list->reason ) continue; - algstr = gcry_pk_algo_name ( list->pubkey_algo ); + algstr = openpgp_pk_algo_name ( list->pubkey_algo ); pk = xmalloc_clear( sizeof *pk ); if( !algstr ) @@ -1616,7 +1618,7 @@ check_sig_and_print( CTX c, KBNODE node ) /* (Indendation below not yet changed to GNU style.) */ - astr = gcry_pk_algo_name ( sig->pubkey_algo ); + astr = openpgp_pk_algo_name ( sig->pubkey_algo ); if(keystrlen()>8) { log_info(_("Signature made %s\n"),asctimestamp(sig->timestamp)); diff --git a/g10/misc.c b/g10/misc.c index 1725258..a09636b 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -64,6 +64,7 @@ #include "call-agent.h" #include "i18n.h" +#include static int string_count_chr (const char *string, int c) @@ -294,7 +295,7 @@ print_pubkey_algo_note( int algo ) { warn=1; log_info (_("WARNING: using experimental public key algorithm %s\n"), - gcry_pk_algo_name (algo)); + openpgp_cipher_algo_name (algo)); } } else if (algo == 20) @@ -365,6 +366,12 @@ map_cipher_gcry_to_openpgp (int algo) } } +int +map_pk_openpgp_to_gcry (int algo) +{ + return (algo==PUBKEY_ALGO_ECDSA ? GCRY_PK_ECDSA : (algo==PUBKEY_ALGO_ECDH ? GCRY_PK_ECDH : algo)); +} + /* Return the block length of an OpenPGP cipher algorithm. */ int @@ -409,7 +416,13 @@ openpgp_cipher_test_algo( int algo ) const char * openpgp_cipher_algo_name (int algo) { - return gnupg_cipher_algo_name (map_cipher_openpgp_to_gcry (algo)); + return gcry_cipher_algo_name (map_cipher_openpgp_to_gcry (algo)); +} + +const char * +openpgp_pk_algo_name (int algo) +{ + return gcry_pk_algo_name ( algo == PUBKEY_ALGO_ECDSA ? GCRY_PK_ECDSA : ( algo == PUBKEY_ALGO_ECDH ? GCRY_PK_ECDH : algo ) ); } int @@ -424,7 +437,13 @@ openpgp_pk_test_algo( int algo ) if (algo < 0 || algo > 110) return gpg_error (GPG_ERR_PUBKEY_ALGO); - return gcry_pk_test_algo (algo); + + if( algo == PUBKEY_ALGO_ECDSA ) + algo = GCRY_PK_ECDSA; + else if( algo == PUBKEY_ALGO_ECDH ) + algo = GCRY_PK_ECDH; + + return gcry_pk_test_algo ( algo ); } int @@ -442,7 +461,12 @@ openpgp_pk_test_algo2( int algo, unsigned int use ) if (algo < 0 || algo > 110) return gpg_error (GPG_ERR_PUBKEY_ALGO); - return gcry_pk_algo_info (algo, GCRYCTL_TEST_ALGO, NULL, &use_buf); + if( algo == PUBKEY_ALGO_ECDSA ) + algo = GCRY_PK_ECDSA; + else if( algo == PUBKEY_ALGO_ECDH ) + algo = GCRY_PK_ECDH; + + return gcry_pk_algo_info ( algo, GCRYCTL_TEST_ALGO, NULL, &use_buf); } int @@ -457,6 +481,7 @@ openpgp_pk_algo_usage ( int algo ) | PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH); break; case PUBKEY_ALGO_RSA_E: + case PUBKEY_ALGO_ECDH: use = PUBKEY_USAGE_ENC; break; case PUBKEY_ALGO_RSA_S: @@ -472,6 +497,8 @@ openpgp_pk_algo_usage ( int algo ) case PUBKEY_ALGO_DSA: use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH; break; + case PUBKEY_ALGO_ECDSA: + use = PUBKEY_USAGE_CERT | PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH; default: break; } @@ -480,7 +507,7 @@ openpgp_pk_algo_usage ( int algo ) /* Map the OpenPGP pubkey algorithm whose ID is contained in ALGO to a string representation of the algorithm name. For unknown algorithm - IDs this function returns "?". */ + IDs this function returns "?". const char * openpgp_pk_algo_name (int algo) { @@ -498,6 +525,7 @@ openpgp_pk_algo_name (int algo) default: return "?"; } } +*/ int @@ -1348,6 +1376,10 @@ pubkey_get_npkey( int algo ) if (algo == GCRY_PK_ELG_E) algo = GCRY_PK_ELG; + else if (algo == PUBKEY_ALGO_ECDSA) + algo = GCRY_PK_ECDSA; + else if (algo == PUBKEY_ALGO_ECDH) + algo = GCRY_PK_ECDH; if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &n)) n = 0; return n; @@ -1361,6 +1393,10 @@ pubkey_get_nskey( int algo ) if (algo == GCRY_PK_ELG_E) algo = GCRY_PK_ELG; + else if (algo == PUBKEY_ALGO_ECDSA) + algo = GCRY_PK_ECDSA; + else if (algo == PUBKEY_ALGO_ECDH) + algo = GCRY_PK_ECDH; if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &n )) n = 0; return n; @@ -1374,6 +1410,10 @@ pubkey_get_nsig( int algo ) if (algo == GCRY_PK_ELG_E) algo = GCRY_PK_ELG; + else if (algo == PUBKEY_ALGO_ECDSA) + algo = GCRY_PK_ECDSA; + else if (algo == PUBKEY_ALGO_ECDH) + algo = GCRY_PK_ECDH; if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NSIGN, NULL, &n)) n = 0; return n; @@ -1387,6 +1427,10 @@ pubkey_get_nenc( int algo ) if (algo == GCRY_PK_ELG_E) algo = GCRY_PK_ELG; + else if (algo == PUBKEY_ALGO_ECDSA) + algo = GCRY_PK_ECDSA; + else if (algo == PUBKEY_ALGO_ECDH) + algo = GCRY_PK_ECDH; if (gcry_pk_algo_info( algo, GCRYCTL_GET_ALGO_NENCR, NULL, &n )) n = 0; return n; @@ -1400,6 +1444,8 @@ pubkey_nbits( int algo, gcry_mpi_t *key ) int rc, nbits; gcry_sexp_t sexp; + assert( algo != GCRY_PK_ECDSA && algo != GCRY_PK_ECDH ); + if( algo == GCRY_PK_DSA ) { rc = gcry_sexp_build ( &sexp, NULL, "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))", @@ -1415,6 +1461,11 @@ pubkey_nbits( int algo, gcry_mpi_t *key ) "(public-key(rsa(n%m)(e%m)))", key[0], key[1] ); } + else if( algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH ) { + rc = gcry_sexp_build ( &sexp, NULL, + "(public-key(ecc(c%m)(q%m)))", + key[0], key[1] /* not affecting the size calculation, so use 'ecc' == 'ecdsa' */ ); + } else return 0; @@ -1455,3 +1506,89 @@ mpi_print (estream_t fp, gcry_mpi_t a, int mode) return n; } +/* + * Write a special size+body mpi a, to OUT. The format of the content of the MPI is + * one byte LEN, following by LEN bytes + */ +int +iobuf_write_size_body_mpi (iobuf_t out, gcry_mpi_t a) +{ + byte buffer[256]; /* Fixed buffer for a public parameter, max possible */ + size_t nbytes = (mpi_get_nbits (a)+7)/8; + int rc; + + if( nbytes > sizeof(buffer) ) { + log_error("mpi with size+body is too large (%u bytes)\n", nbytes); + return gpg_error (GPG_ERR_TOO_LARGE); + } + + rc = gcry_mpi_print (GCRYMPI_FMT_USG, buffer, sizeof(buffer), &nbytes, a); + if( rc ) { + log_error("Failed to exported size+body mpi\n"); + return rc; + } + if( nbytes < 2 || buffer[0] != nbytes-1 ) { + if( nbytes > 2 ) + log_error("Internal size mismatch in mpi size+body: %02x != %02x (other bytes: %02x %02x ... %02x %02x)\n", + buffer[0], nbytes-1, buffer[1], buffer[2], buffer[nbytes-2], buffer[nbytes-1]); + else + log_error("Internal size mismatch in mpi size+body: only %d bytes\n", nbytes ); + return gpg_error (GPG_ERR_INV_DATA); + } + return iobuf_write( out, buffer, nbytes ); +} + +/* + * Read a special size+body from inp into body[body_max_size] and return it in a buffer and as MPI. + * On success the number of consumed bytes will body[0]+1. + * The format of the content of the returned MPI is one byte LEN, following by LEN bytes. + * Caller is expected to pre-allocate fixed-size 255 byte buffer (or smaller when appropriate). + */ +int +iobuf_read_size_body( iobuf_t inp, byte *body, int body_max_size, int pktlen, gcry_mpi_t *out ) { + unsigned n; + int rc; + gcry_mpi_t result; + + *out = NULL; + + if( (n = iobuf_readbyte(inp)) == -1 ) { + return G10ERR_INVALID_PACKET; + } + if( n >= body_max_size || n < 2) { + log_error("invalid size+body field\n"); + return G10ERR_INVALID_PACKET; + } + body[0] = n; + if( (n = iobuf_read(inp, body+1, n)) == -1 ) { + log_error("invalid size+body field\n"); + return G10ERR_INVALID_PACKET; + } + if( n+1 > pktlen ) { + log_error("size+body field is larger than the packet\n"); + return G10ERR_INVALID_PACKET; + } + rc = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, body, n+1, NULL); + if (rc) + log_fatal ("mpi_scan failed: %s\n", gpg_strerror (rc)); + + *out = result; + + return rc; +} + + +/* pkey[1] or skey[1] is Q for ECDSA, which is an uncompressed point, i.e. 04 */ +int ecdsa_qbits_from_Q( int qbits ) { + if( qbits%8>3 ) { + log_error(_("ECDSA public key is expected to be in SEC encoding multiple of 8 bits\n")); + return 0; + } + qbits -= qbits%8; + qbits /= 2; + return qbits; +} + + + + diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 3714739..42d680a 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -939,20 +939,40 @@ parse_pubkeyenc (IOBUF inp, int pkttype, unsigned long pktlen, } else { - for (i = 0; i < ndata; i++) - { - n = pktlen; - k->data[i] = mpi_read (inp, &n, 0); - pktlen -= n; - if (list_mode) - { - es_fprintf (listfp, "\tdata: "); - mpi_print (listfp, k->data[i], mpi_print_mode); - es_putc ('\n', listfp); - } - if (!k->data[i]) - rc = gpg_error (GPG_ERR_INV_PACKET); - } + if( k->pubkey_algo != PUBKEY_ALGO_ECDH ) { + for (i = 0; i < ndata; i++) + { + n = pktlen; + k->data[i] = mpi_read (inp, &n, 0); + pktlen -= n; + if (list_mode) + { + es_fprintf (listfp, "\tdata: "); + mpi_print (listfp, k->data[i], mpi_print_mode); + es_putc ('\n', listfp); + } + if (!k->data[i]) + rc = gpg_error (GPG_ERR_INV_PACKET); + } + } + else + { + byte encr_buf[255]; + assert( ndata == 2 ); + n = pktlen; k->data[0] = mpi_read(inp, &n, 0); pktlen -=n; + rc = iobuf_read_size_body( inp, encr_buf, sizeof(encr_buf), pktlen, k->data+1 ); + if( rc ) + goto leave; + if( list_mode ) { + es_fprintf (listfp, "\tdata: "); + mpi_print(listfp, k->data[0], mpi_print_mode ); + es_putc ('\n', listfp); + es_fprintf (listfp, "\tdata: [% 3d bytes] ", encr_buf[0]); + mpi_print(listfp, k->data[1], mpi_print_mode ); + es_putc ('\n', listfp); + } + pktlen -= (encr_buf[0]+1); + } } leave: @@ -1926,20 +1946,61 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, else { /* Fill in public key parameters. */ - 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( algorithm != PUBKEY_ALGO_ECDSA && algorithm != PUBKEY_ALGO_ECDH ) { + 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]) + err = gpg_error (GPG_ERR_INV_PACKET); + } + } + else { + /* note that the code in this function ignores the errors */ + byte name_oid[256]; + err = iobuf_read_size_body( inp, name_oid, sizeof(name_oid), pktlen, pk->pkey+0 ); + if( err ) + goto leave; + n = name_oid[0]; + if( list_mode ) + es_fprintf (listfp, "\tpkey[0]: curve OID [%d] ...%02x %02x\n", + n, name_oid[1+n-2], name_oid[1+n-1] ); + pktlen -= (n+1); + /* set item [1], which corresponds to the public key; these two fields are all we need to uniquely define the key */ + // log_debug("Parsing ecc public key in the public packet, pktlen=%lu\n", pktlen); + n = pktlen; pk->pkey[1] = mpi_read( inp, &n, 0 ); pktlen -=n; + if( pk->pkey[1]==NULL ) + err = gpg_error(G10ERR_INVALID_PACKET); + else if( list_mode ) { + es_fprintf (listfp, "\tpkey[1]: "); + mpi_print(listfp, pk->pkey[1], mpi_print_mode); + es_putc ('\n', listfp); } - if (!pk->pkey[i]) - err = gpg_error (GPG_ERR_INV_PACKET); - } + /* One more field for ECDH */ + if( algorithm == PUBKEY_ALGO_ECDH ) { +#define kek_params name_oid + err = iobuf_read_size_body( inp, kek_params, sizeof(kek_params), pktlen, pk->pkey+2 ); + if( err ) + goto leave; + n = kek_params[0]; + if( kek_params[1] != 1 ) { + log_error("invalid ecdh KEK parameters field type in private key: understand type 1, but found 0x%02x\n", kek_params[1]); + err = gpg_error(G10ERR_INVALID_PACKET); + goto leave; + } + if( list_mode ) + es_fprintf (listfp, "\tpkey[2]: KEK params type=01 hash:%d sym-algo:%d\n", kek_params[1+n-2], kek_params[1+n-1] ); + pktlen -= (n+1); +#undef kek_params + } + } if (err) goto leave; } diff --git a/g10/passphrase.c b/g10/passphrase.c index 9f1218b..f29fca7 100644 --- a/g10/passphrase.c +++ b/g10/passphrase.c @@ -323,7 +323,7 @@ passphrase_get ( u32 *keyid, int mode, const char *cacheid, int repeat, { char *uid; size_t uidlen; - const char *algo_name = gcry_pk_algo_name ( pk->pubkey_algo ); + const char *algo_name = openpgp_pk_algo_name ( pk->pubkey_algo ); const char *timestr; char *maink; @@ -585,7 +585,7 @@ passphrase_to_dek_ext (u32 *keyid, int pubkey_algo, if ( !get_pubkey( pk, keyid ) ) { - const char *s = gcry_pk_algo_name ( pk->pubkey_algo ); + 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), @@ -690,7 +690,7 @@ gpg_format_keydesc (PKT_public_key *pk, int mode, int escaped) char *desc; const char *prompt; - algo_name = gcry_pk_algo_name (pk->pubkey_algo); + algo_name = openpgp_pk_algo_name (pk->pubkey_algo); timestr = strtimestamp (pk->timestamp); uid = get_user_id (pk->keyid, &uidlen); diff --git a/g10/pkglue.c b/g10/pkglue.c index 14a2753..f785919 100644 --- a/g10/pkglue.c +++ b/g10/pkglue.c @@ -27,9 +27,10 @@ #include "gpg.h" #include "util.h" #include "pkglue.h" +#include "main.h" -static gcry_mpi_t +gcry_mpi_t mpi_from_sexp (gcry_sexp_t sexp, const char * item) { gcry_sexp_t list; @@ -44,6 +45,70 @@ mpi_from_sexp (gcry_sexp_t sexp, const char * item) } +/**************** + * Emulate our old PK interface here - sometime in the future we might + * change the internal design to directly fit to libgcrypt. + */ +int +pk_sign (int algo, gcry_mpi_t * data, gcry_mpi_t hash, gcry_mpi_t * skey) +{ + gcry_sexp_t s_sig, s_hash, s_skey; + int rc; + int gcry_pkalgo = map_pk_openpgp_to_gcry( algo ); + + /* make a sexp from skey */ + if (gcry_pkalgo == GCRY_PK_DSA) + { + rc = gcry_sexp_build (&s_skey, NULL, + "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))", + skey[0], skey[1], skey[2], skey[3], skey[4]); + } + else if (gcry_pkalgo == GCRY_PK_RSA || gcry_pkalgo == GCRY_PK_RSA_S) + { + rc = gcry_sexp_build (&s_skey, NULL, + "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))", + skey[0], skey[1], skey[2], skey[3], skey[4], + skey[5]); + } + else if (gcry_pkalgo == GCRY_PK_ELG || gcry_pkalgo == GCRY_PK_ELG_E) + { + rc = gcry_sexp_build (&s_skey, NULL, + "(private-key(elg(p%m)(g%m)(y%m)(x%m)))", + skey[0], skey[1], skey[2], skey[3]); + } + else if (gcry_pkalgo == GCRY_PK_ECDSA) + { + rc = gcry_sexp_build (&s_skey, NULL, + "(private-key(ecdsa(c%m)(q%m)(d%m)))", + skey[0], skey[1], skey[2] ); + } + else + return GPG_ERR_PUBKEY_ALGO; + + if (rc) + BUG (); + + /* put hash into a S-Exp s_hash */ + if (gcry_sexp_build (&s_hash, NULL, "%m", hash)) + BUG (); + + rc = gcry_pk_sign (&s_sig, s_hash, s_skey); + gcry_sexp_release (s_hash); + gcry_sexp_release (s_skey); + + if (rc) + ; + else if (algo == GCRY_PK_RSA || algo == GCRY_PK_RSA_S) + data[0] = mpi_from_sexp (s_sig, "s"); + else + { + data[0] = mpi_from_sexp (s_sig, "r"); + data[1] = mpi_from_sexp (s_sig, "s"); + } + + gcry_sexp_release (s_sig); + return rc; +} /**************** * Emulate our old PK interface here - sometime in the future we might @@ -54,25 +119,31 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey) { gcry_sexp_t s_sig, s_hash, s_pkey; int rc; + const int gcry_pkalgo = map_pk_openpgp_to_gcry( algo ); /* make a sexp from pkey */ - if (algo == GCRY_PK_DSA) + if (gcry_pkalgo == GCRY_PK_DSA) { rc = gcry_sexp_build (&s_pkey, NULL, "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))", pkey[0], pkey[1], pkey[2], pkey[3]); } - else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E) + else if (gcry_pkalgo == GCRY_PK_ELG || gcry_pkalgo == GCRY_PK_ELG_E) { rc = gcry_sexp_build (&s_pkey, NULL, "(public-key(elg(p%m)(g%m)(y%m)))", pkey[0], pkey[1], pkey[2]); } - else if (algo == GCRY_PK_RSA || algo == GCRY_PK_RSA_S) + else if (gcry_pkalgo == GCRY_PK_RSA || gcry_pkalgo == GCRY_PK_RSA_S) { rc = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]); } + else if (gcry_pkalgo == GCRY_PK_ECDSA) /* same as GCRY_PK_ECDH */ + { + rc = gcry_sexp_build (&s_pkey, NULL, + "(public-key(ecdsa(c%m)(q%m)))", pkey[0], pkey[1]); + } else return GPG_ERR_PUBKEY_ALGO; @@ -85,7 +156,7 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey) /* Put data into a S-Exp s_sig. */ s_sig = NULL; - if (algo == GCRY_PK_DSA) + if (gcry_pkalgo == GCRY_PK_DSA) { if (!data[0] || !data[1]) rc = gpg_error (GPG_ERR_BAD_MPI); @@ -93,7 +164,15 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey) rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(dsa(r%m)(s%m)))", data[0], data[1]); } - else if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E) + else if (gcry_pkalgo == GCRY_PK_ECDSA) + { + if (!data[0] || !data[1]) + rc = gpg_error (GPG_ERR_BAD_MPI); + else + rc = gcry_sexp_build (&s_sig, NULL, + "(sig-val(ecdsa(r%m)(s%m)))", data[0], data[1]); + } + else if (gcry_pkalgo == GCRY_PK_ELG || gcry_pkalgo == GCRY_PK_ELG_E) { if (!data[0] || !data[1]) rc = gpg_error (GPG_ERR_BAD_MPI); @@ -101,7 +180,7 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey) rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(elg(r%m)(s%m)))", data[0], data[1]); } - else if (algo == GCRY_PK_RSA || algo == GCRY_PK_RSA_S) + else if (gcry_pkalgo == GCRY_PK_RSA || gcry_pkalgo == GCRY_PK_RSA_S) { if (!data[0]) rc = gpg_error (GPG_ERR_BAD_MPI); @@ -128,7 +207,7 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey) * change the internal design to directly fit to libgcrypt. */ int -pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey) +pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t * pkey) { gcry_sexp_t s_ciph, s_data, s_pkey; int rc; @@ -146,6 +225,10 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey) "(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]); } + else if (algo == PUBKEY_ALGO_ECDH) + { + return pk_ecdh_encrypt( resarr, pk_fp, data, pkey ); + } else return GPG_ERR_PUBKEY_ALGO; @@ -166,7 +249,7 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey) else { /* add better error handling or make gnupg use S-Exp directly */ resarr[0] = mpi_from_sexp (s_ciph, "a"); - if (algo != GCRY_PK_RSA && algo != GCRY_PK_RSA_E) + if (algo != GCRY_PK_RSA && algo != GCRY_PK_RSA_E && algo != PUBKEY_ALGO_ECDH) resarr[1] = mpi_from_sexp (s_ciph, "b"); } @@ -181,7 +264,7 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, gcry_mpi_t * pkey) * change the internal design to directly fit to libgcrypt. */ int -pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data, +pk_decrypt (int algo, gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t * data, gcry_mpi_t * skey) { gcry_sexp_t s_skey, s_data, s_plain; @@ -202,6 +285,9 @@ pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data, skey[0], skey[1], skey[2], skey[3], skey[4], skey[5]); } + else if( algo == PUBKEY_ALGO_ECDH ) { + return pk_ecdh_decrypt( result, sk_fp, data, skey ); + } else return GPG_ERR_PUBKEY_ALGO; @@ -244,3 +330,48 @@ pk_decrypt (int algo, gcry_mpi_t * result, gcry_mpi_t * data, return 0; } + +/* Check whether SKEY is a suitable secret key. */ +int +pk_check_secret_key (int algo, gcry_mpi_t *skey) +{ + gcry_sexp_t s_skey; + int rc; + const int gcry_pkalgo = map_pk_openpgp_to_gcry( algo ); + + if (gcry_pkalgo == GCRY_PK_DSA) + { + rc = gcry_sexp_build (&s_skey, NULL, + "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))", + skey[0], skey[1], skey[2], skey[3], skey[4]); + } + else if (gcry_pkalgo == GCRY_PK_ELG || gcry_pkalgo == GCRY_PK_ELG_E) + { + rc = gcry_sexp_build (&s_skey, NULL, + "(private-key(elg(p%m)(g%m)(y%m)(x%m)))", + skey[0], skey[1], skey[2], skey[3]); + } + else if (gcry_pkalgo == GCRY_PK_RSA + || gcry_pkalgo == GCRY_PK_RSA_S || gcry_pkalgo == GCRY_PK_RSA_E) + { + rc = gcry_sexp_build (&s_skey, NULL, + "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))", + skey[0], skey[1], skey[2], skey[3], skey[4], + skey[5]); + } + else if (gcry_pkalgo == GCRY_PK_ECDSA || gcry_pkalgo == GCRY_PK_ECDH) + { + rc = gcry_sexp_build (&s_skey, NULL, + "(private-key(ecdsa(c%m)(q%m)(d%m)))", + skey[0], skey[1], skey[2] ); + } + else + return GPG_ERR_PUBKEY_ALGO; + + if (!rc) + { + rc = gcry_pk_testkey (s_skey); + gcry_sexp_release (s_skey); + } + return rc; +} diff --git a/g10/pkglue.h b/g10/pkglue.h index f97def1..0d51948 100644 --- a/g10/pkglue.h +++ b/g10/pkglue.h @@ -20,13 +20,23 @@ #ifndef GNUPG_G10_PKGLUE_H #define GNUPG_G10_PKGLUE_H +gcry_mpi_t mpi_from_sexp (gcry_sexp_t sexp, const char * item); + +int pk_sign (int algo, gcry_mpi_t *data, gcry_mpi_t hash, + gcry_mpi_t *skey); int pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey); int pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, + const byte fp[MAX_FINGERPRINT_LEN], gcry_mpi_t *pkey); -int pk_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data, +int pk_decrypt (int algo, gcry_mpi_t *result, const byte fp[MAX_FINGERPRINT_LEN], gcry_mpi_t *data, gcry_mpi_t *skey); int pk_check_secret_key (int algo, gcry_mpi_t *skey); +int pk_ecdh_encrypt (gcry_mpi_t * resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t * pkey); +int pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t *data, gcry_mpi_t * skey); + +gcry_mpi_t pk_ecdh_default_params_to_mpi( int qbits ); +byte *pk_ecdh_default_params( int qbits, size_t *sizeout ); #endif /*GNUPG_G10_PKGLUE_H*/ diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 312b591..a5224e2 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -145,6 +145,8 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) gcry_sexp_t s_data; char *desc; char *keygrip; + byte fp[MAX_FINGERPRINT_LEN]; + size_t fpn; /* Get the keygrip. */ err = hexkeygrip_from_pk (sk, &keygrip); @@ -174,9 +176,12 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) if (err) goto leave; + fingerprint_from_pk( sk, fp, &fpn ); + assert( fpn == 20 ); + /* Decrypt. */ desc = gpg_format_keydesc (sk, 0, 1); - err = agent_pkdecrypt (NULL, keygrip, desc, s_data, &frame, &nframe); + err = agent_pkdecrypt (NULL, keygrip, desc, s_data, fp, &frame, &nframe); xfree (desc); gcry_sexp_release (s_data); if (err) @@ -202,28 +207,41 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) if (DBG_CIPHER) log_printhex ("DEK frame:", frame, nframe); n = 0; - if (!card) - { - if (n + 7 > nframe) - { - err = gpg_error (G10ERR_WRONG_SECKEY); - goto leave; - } - if (frame[n] == 1 && frame[nframe - 1] == 2) - { - log_info (_("old encoding of the DEK is not supported\n")); - err = gpg_error (G10ERR_CIPHER_ALGO); - goto leave; - } - if (frame[n] != 2) /* Something went wrong. */ - { - err = gpg_error (G10ERR_WRONG_SECKEY); - goto leave; - } - for (n++; n < nframe && frame[n]; n++) /* Skip the random bytes. */ - ; - n++; /* Skip the zero byte. */ + + if( sk->pubkey_algo != PUBKEY_ALGO_ECDH ) { + if (!card) + { + if (n + 7 > nframe) + { + err = gpg_error (G10ERR_WRONG_SECKEY); + goto leave; + } + if (frame[n] == 1 && frame[nframe - 1] == 2) + { + log_info (_("old encoding of the DEK is not supported\n")); + err = gpg_error (G10ERR_CIPHER_ALGO); + goto leave; + } + if (frame[n] != 2) /* Something went wrong. */ + { + err = gpg_error (G10ERR_WRONG_SECKEY); + goto leave; + } + for (n++; n < nframe && frame[n]; n++) /* Skip the random bytes. */ + ; + n++; /* Skip the zero byte. */ + } + } + else { + /* Allow double padding for the benefit of DEK size concealment. + * Higher than this is wasteful. + */ + if( frame[nframe-1] > 8*2 || nframe <= 8 ) { + err = G10ERR_WRONG_SECKEY; goto leave; } + nframe -= frame[nframe-1]; /* remove padding */ + assert( n==0 ); /* used just bellow */ + } if (n + 4 > nframe) { diff --git a/g10/seskey.c b/g10/seskey.c index ee5584c..4cc9158 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -27,6 +27,7 @@ #include "gpg.h" #include "util.h" #include "cipher.h" +#include "options.h" #include "main.h" #include "i18n.h" @@ -73,15 +74,48 @@ make_session_key( DEK *dek ) * returns: A mpi with the session key (caller must free) */ gcry_mpi_t -encode_session_key (DEK *dek, unsigned int nbits) +encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits) { size_t nframe = (nbits+7) / 8; byte *p; byte *frame; int i,n; - u16 csum; + u16 csum = 0; gcry_mpi_t a; + if( DBG_CIPHER ) + log_debug("encode_session_key: encoding %d byte DEK", dek->keylen); + + for( p = dek->key, i=0; i < dek->keylen; i++ ) + csum += *p++; + + /* Shortcut for ECDH. It's padding is minimal to simply make the output be a multiple of 8 bytes. */ + if( openpgp_pk_algo == PUBKEY_ALGO_ECDH ) { + /* pad to 8 byte granulatiry; the padding byte is the number of padded bytes. + * A DEK(k bytes) CSUM(2 bytes) 0x 0x 0x 0x ... 0x + * +---- x times ---+ + */ + nframe = ( 1 + dek->keylen + 2 /* the value so far is always odd */ + 7 ) & (~7); + assert( !(nframe%8) && nframe > 1 + dek->keylen + 2 ); /* alg+key+csum fit and the size is congruent to 8 */ + frame = xmalloc_secure( nframe ); + n = 0; + frame[n++] = dek->algo; + memcpy( frame+n, dek->key, dek->keylen ); n += dek->keylen; + frame[n++] = csum >>8; + frame[n++] = csum; + i = nframe - n; /* number padded bytes */ + memset( frame+n, i, i );/* use it as the value of each padded byte */ + assert( n+i == nframe ); + + if( DBG_CIPHER ) + log_debug("encode_session_key: [%d] %02x %02x %02x ... %02x %02x %02x", nframe, frame[0],frame[1],frame[2], frame[nframe-3],frame[nframe-2],frame[nframe-1]); + + if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, nframe, &nframe)) + BUG(); + xfree(frame); + return a; + } + /* The current limitation is that we can only use a session key * whose length is a multiple of BITS_PER_MPI_LIMB * I think we can live with that. @@ -103,9 +137,6 @@ encode_session_key (DEK *dek, unsigned int nbits) * cipher algorithm (20 is used with blowfish160). * CSUM is the 16 bit checksum over the DEK */ - csum = 0; - for( p = dek->key, i=0; i < dek->keylen; i++ ) - csum += *p++; frame = xmalloc_secure( nframe ); n = 0; @@ -161,8 +192,8 @@ do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits, gcry_mpi_t a; if( len + asnlen + 4 > nframe ) - log_bug("can't encode a %d bit MD into a %d bits frame\n", - (int)(len*8), (int)nbits); + log_bug("can't encode a %d bit MD into a %d bits frame, algo=%d\n", + (int)(len*8), (int)nbits, algo); /* We encode the MD in this way: * @@ -209,16 +240,23 @@ gcry_mpi_t encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo) { gcry_mpi_t frame; + int gcry_pkalgo; assert (hash_algo); assert (pk); - if (pk->pubkey_algo == GCRY_PK_DSA) + gcry_pkalgo = map_pk_openpgp_to_gcry( pk->pubkey_algo ); + + if (gcry_pkalgo == GCRY_PK_DSA || gcry_pkalgo == GCRY_PK_ECDSA ) { /* It's a DSA signature, so find out the size of q. */ size_t qbytes = gcry_mpi_get_nbits (pk->pkey[1]); + /* pkey[1] is Q for ECDSA, which is an uncompressed point, i.e. 04 */ + if( gcry_pkalgo==GCRY_PK_ECDSA ) + qbytes = ecdsa_qbits_from_Q( qbytes ); + /* Make sure it is a multiple of 8 bits. */ if(qbytes%8) @@ -236,7 +274,8 @@ encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo) DSA. ;) */ if (qbytes < 160) { - log_error (_("DSA key %s uses an unsafe (%zu bit) hash\n"), + log_error (_("%s key %s uses an unsafe (%zu bit) hash\n"), + gcry_pk_algo_name( gcry_pkalgo ), keystr_from_pk (pk), qbytes); return NULL; } @@ -245,10 +284,16 @@ encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo) /* Check if we're too short. Too long is safe as we'll automatically left-truncate. */ - if (gcry_md_get_algo_dlen (hash_algo) < qbytes) + /* This checks would require the use of SHA512 with ECDSA 512. I think this is overkill to fail in this case. + * Therefore, relax the check, but only for ECDSA keys. We may need to adjust it later for general case. + * ( Note that the check will never pass for ECDSA 521 anyway as the only hash that intended to match it is SHA 512, but 512 < 521 ). + */ + //if (gcry_md_get_algo_dlen (hash_algo) < qbytes ) + if (gcry_md_get_algo_dlen (hash_algo) < ((gcry_pkalgo==GCRY_PK_ECDSA && qbytes>(521)/8) ? 512/8 : qbytes) ) { - log_error (_("DSA key %s requires a %zu bit or larger hash\n"), - keystr_from_pk(pk), qbytes*8); + log_error (_("%s key %s requires a %zu bit or larger hash, used hash-algo=%d\n"), + gcry_pk_algo_name( gcry_pkalgo ), + keystr_from_pk(pk), qbytes*8, hash_algo); return NULL; } diff --git a/g10/sign.c b/g10/sign.c index 5c00424..ccf7964 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -227,21 +227,6 @@ hash_sigversion_to_magic (gcry_md_hd_t md, const PKT_signature *sig) } } - -static gcry_mpi_t -mpi_from_sexp (gcry_sexp_t sexp, const char * item) -{ - gcry_sexp_t list; - gcry_mpi_t data; - - list = gcry_sexp_find_token (sexp, item, 0); - assert (list); - data = gcry_sexp_nth_mpi (list, 1, 0); - assert (data); - gcry_sexp_release (list); - return data; -} - /* Perform the sign operation. If CACHE_NONCE is given the agent is advised to use that cached passphrase fro the key. */ static int @@ -418,7 +403,7 @@ match_dsa_hash (unsigned int qbytes) if (qbytes <= 48) return DIGEST_ALGO_SHA384; - if (qbytes <= 64) + if (qbytes <= 66 ) /* 66 corresponds to 521 (64 to 512) */ return DIGEST_ALGO_SHA512; return DEFAULT_DIGEST_ALGO; @@ -451,9 +436,13 @@ hash_for (PKT_public_key *pk) { return recipient_digest_algo; } - else if (pk->pubkey_algo == PUBKEY_ALGO_DSA) + else if(pk->pubkey_algo==PUBKEY_ALGO_DSA || pk->pubkey_algo==PUBKEY_ALGO_ECDSA ) { - unsigned int qbytes = gcry_mpi_get_nbits (pk->pkey[1]) / 8; + unsigned int qbytes = gcry_mpi_get_nbits (pk->pkey[1]); + + if( pk->pubkey_algo==PUBKEY_ALGO_ECDSA ) + qbytes = ecdsa_qbits_from_Q(qbytes); + qbytes = qbytes/8; /* It's a DSA key, so find a hash that is the same size as q or larger. If q is 160, assume it is an old DSA key and use a @@ -935,10 +924,13 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr, for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_DSA) + if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_DSA || sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA ) { - int temp_hashlen = gcry_mpi_get_nbits - (sk_rover->pk->pkey[1])+7/8; + int temp_hashlen = gcry_mpi_get_nbits(sk_rover->pk->pkey[1]); + + if( sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA ) + temp_hashlen = ecdsa_qbits_from_Q( temp_hashlen ); + temp_hashlen = (temp_hashlen+7)/8; /* Pick a hash that is large enough for our largest q */ @@ -1494,7 +1486,9 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, && pk->version<4 && sigversion<4) digest_algo = DIGEST_ALGO_MD5; else if(pksk->pubkey_algo==PUBKEY_ALGO_DSA) - digest_algo = match_dsa_hash (gcry_mpi_get_nbits (pksk->pkey[1])/8); + digest_algo = match_dsa_hash (gcry_mpi_get_nbits (pksk->pkey[1])/8 ); + else if(pksk->pubkey_algo==PUBKEY_ALGO_ECDSA ) + digest_algo = match_dsa_hash (ecdsa_qbits_from_Q( gcry_mpi_get_nbits (pksk->pkey[1]) ) / 8); else digest_algo = DIGEST_ALGO_SHA1; } diff --git a/g10/pkglue.h b/g10/verify-stubs.c similarity index 56% copy from g10/pkglue.h copy to g10/verify-stubs.c index f97def1..d1f0aa1 100644 --- a/g10/pkglue.h +++ b/g10/verify-stubs.c @@ -1,5 +1,6 @@ -/* pkglue.h - public key operations definitions - * Copyright (C) 2003 Free Software Foundation, Inc. +/* To satisfy the linker for the gpgv target + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, + * 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -17,16 +18,13 @@ * along with this program; if not, see . */ -#ifndef GNUPG_G10_PKGLUE_H -#define GNUPG_G10_PKGLUE_H +#include -int pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, - gcry_mpi_t *pkey); -int pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, - gcry_mpi_t *pkey); -int pk_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data, - gcry_mpi_t *skey); -int pk_check_secret_key (int algo, gcry_mpi_t *skey); +#include +#include "gpg.h" +#include "main.h" - -#endif /*GNUPG_G10_PKGLUE_H*/ +int +pk_ecc_keypair_gen( PKT_public_key **pk_out, int algo, int keygen_flags, char **cache_nonce_addr, unsigned nbits) { + return GPG_ERR_NOT_IMPLEMENTED; +} diff --git a/g13/utils.c b/g13/utils.c index ef0c572..1ea7f32 100644 --- a/g13/utils.c +++ b/g13/utils.c @@ -176,5 +176,7 @@ next_tuple (tupledesc_t tupledesc, unsigned int *r_tag, size_t *r_length) } return NULL; -} +} + + diff --git a/g13/utils.h b/g13/utils.h index ef718d6..528ce16 100644 --- a/g13/utils.h +++ b/g13/utils.h @@ -38,7 +38,7 @@ const void *find_tuple (tupledesc_t tupledesc, unsigned int tag, size_t *r_length); const void *next_tuple (tupledesc_t tupledesc, unsigned int *r_tag, size_t *r_length); - +char *mpi2hex( gcry_mpi_t m ); #endif /*G13_UTILS_H*/ diff --git a/include/cipher.h b/include/cipher.h index 8e19828..65cd59e 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -56,6 +56,8 @@ #define PUBKEY_ALGO_RSA_S /* 3 */ GCRY_PK_RSA_S /* RSA sign only. */ #define PUBKEY_ALGO_ELGAMAL_E /* 16 */ GCRY_PK_ELG_E /* Elgamal encr only */ #define PUBKEY_ALGO_DSA /* 17 */ GCRY_PK_DSA +#define PUBKEY_ALGO_ECDH 18 /* corresponds to GCRY_PK_ECDH ECC DH; encrypt only */ +#define PUBKEY_ALGO_ECDSA 19 /* corresponds to GCRY_PK_ECDSA ECC DSA; sign only */ #define PUBKEY_ALGO_ELGAMAL /* 20 */ GCRY_PK_ELG /* Elgamal encr+sign */ #define PUBKEY_USAGE_SIG GCRY_PK_USAGE_SIGN /* Good for signatures. */ diff --git a/kbx/keybox-openpgp.c b/kbx/keybox-openpgp.c index 0968cf8..6c9410e 100644 --- a/kbx/keybox-openpgp.c +++ b/kbx/keybox-openpgp.c @@ -186,7 +186,7 @@ next_packet (unsigned char const **bufptr, size_t *buflen, } -/* Parse a key packet and store the ionformation in KI. */ +/* Parse a key packet and store the information in KI. */ static gpg_error_t parse_key (const unsigned char *data, size_t datalen, struct _keybox_openpgp_key_info *ki) @@ -243,6 +243,11 @@ parse_key (const unsigned char *data, size_t datalen, case 17: /* DSA */ npkey = 4; break; + case 18: /* ECDH */ + npkey = 3; + case 19: /* ECDSA */ + npkey = 2; + break; default: /* Unknown algorithm. */ return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM); } commit 7bbc07fde07f3fd57077887498bdff488ec96438 Author: Andrey Jivsov Date: Wed Jan 5 17:31:47 2011 -0800 Make sure that --disable-optimization works in its attempt to replace -Ox with -O0. diff --git a/configure.ac b/configure.ac index b6ed4b3..9757330 100644 --- a/configure.ac +++ b/configure.ac @@ -1466,7 +1466,7 @@ AC_ARG_ENABLE(optimization, AC_HELP_STRING([--disable-optimization], [disable compiler optimization]), [if test $enableval = no ; then - CFLAGS=`echo $CFLAGS | sed 's/-O[[0-9]]//'` + CFLAGS=`echo $CFLAGS | sed s/-O[[1-9]]\ /-O0\ /g` fi]) # ----------------------------------------------------------------------- hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Thu Jan 6 09:08:31 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Thu, 06 Jan 2011 09:08:31 +0100 Subject: [git] GCRYPT - branch, ECC-INTEGRATION-1-5, created. libgcrypt-1.4.4-50-g2c32b63 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, ECC-INTEGRATION-1-5 has been created at 2c32b631acc1637c1d7826bcdcecf6c0ae9ce7fc (commit) - Log ----------------------------------------------------------------- commit 2c32b631acc1637c1d7826bcdcecf6c0ae9ce7fc Author: Andrey Jivsov Date: Wed Jan 5 23:37:26 2011 -0800 Integrating http://code.google.com/p/gnupg-ecc/source/detail?r=15 . This merge went smoothly and didn't need any code written (as opposed to parallel gnupg integration). The checked in code was tested through gnupg with 'gnupg --gen-key (select ECC)'. This change corresponds to earlier check in gnupg project. This branch, ECC-INTEGRATION-1-5, corresponds to ECC-INTEGRATION-2-1 in gnupg project. diff --git a/cipher/ecc.c b/cipher/ecc.c index bcfab05..fdcbb4c 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -58,7 +58,9 @@ #include "g10lib.h" #include "mpi.h" #include "cipher.h" +#include +#define MAX_ECC_OID_LEN 16 /* Definition of a curve. */ typedef struct @@ -68,6 +70,10 @@ typedef struct gcry_mpi_t b; /* Second coefficient of the Weierstrass equation. */ mpi_point_t G; /* Base point (generator). */ gcry_mpi_t n; /* Order of G. */ + /* one byte length, followed by DER representation of curve OID: + * N byte OID is encoded as N+1 bytes as follows: N x0 x1 ... xN + */ + byte name_oid[MAX_ECC_OID_LEN]; } elliptic_curve_t; @@ -120,22 +126,26 @@ static const struct { NULL, NULL} }; +static const byte curve_oid_NISTP256[] = { 8, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07 }; +static const byte curve_oid_NISTP384[] = { 5, 0x2B, 0x81, 0x04, 0x00, 0x22 }; +static const byte curve_oid_NISTP521[] = { 5, 0x2B, 0x81, 0x04, 0x00, 0x23 }; - -/* This static table defines all available curves. */ -static const struct -{ +typedef struct { const char *desc; /* Description of the curve. */ unsigned int nbits; /* Number of bits. */ unsigned int fips:1; /* True if this is a FIPS140-2 approved curve. */ + const byte *name_oid; /* points to LEN + curve DER OID, optional */ const char *p; /* Order of the prime field. */ const char *a, *b; /* The coefficients. */ const char *n; /* The order of the base point. */ const char *g_x, *g_y; /* Base point. */ -} domain_parms[] = +} ecc_domain_parms_t; + +/* This static table defines all available curves. */ +static const ecc_domain_parms_t domain_parms[] = { { - "NIST P-192", 192, 1, + "NIST P-192", 192, 1, NULL, "0xfffffffffffffffffffffffffffffffeffffffffffffffff", "0xfffffffffffffffffffffffffffffffefffffffffffffffc", "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", @@ -145,7 +155,7 @@ static const struct "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" }, { - "NIST P-224", 224, 1, + "NIST P-224", 224, 1, NULL, "0xffffffffffffffffffffffffffffffff000000000000000000000001", "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe", "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", @@ -155,7 +165,7 @@ static const struct "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" }, { - "NIST P-256", 256, 1, + "NIST P-256", 256, 1, curve_oid_NISTP256, "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff", "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc", "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", @@ -165,7 +175,7 @@ static const struct "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5" }, { - "NIST P-384", 384, 1, + "NIST P-384", 384, 1, curve_oid_NISTP384, "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" "ffffffff0000000000000000ffffffff", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" @@ -181,7 +191,7 @@ static const struct "0a60b1ce1d7e819d7a431d7c90ea0e5f" }, { - "NIST P-521", 521, 1, + "NIST P-521", 521, 1, curve_oid_NISTP521, "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" @@ -197,7 +207,7 @@ static const struct "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650" }, - { "brainpoolP160r1", 160, 0, + { "brainpoolP160r1", 160, 0, NULL, "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f", "0x340e7be2a280eb74e2be61bada745d97e8f7c300", "0x1e589a8595423412134faa2dbdec95c8d8675e58", @@ -206,7 +216,7 @@ static const struct "0x1667cb477a1a8ec338f94741669c976316da6321" }, - { "brainpoolP192r1", 192, 0, + { "brainpoolP192r1", 192, 0, NULL, "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297", "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef", "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9", @@ -215,7 +225,7 @@ static const struct "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f" }, - { "brainpoolP224r1", 224, 0, + { "brainpoolP224r1", 224, 0, NULL, "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff", "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43", "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b", @@ -224,7 +234,7 @@ static const struct "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd" }, - { "brainpoolP256r1", 256, 0, + { "brainpoolP256r1", 256, 0, NULL, "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377", "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9", "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6", @@ -233,7 +243,7 @@ static const struct "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997" }, - { "brainpoolP320r1", 320, 0, + { "brainpoolP320r1", 320, 0, NULL, "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28" "fcd412b1f1b32e27", "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4" @@ -248,7 +258,7 @@ static const struct "d35245d1692e8ee1" }, - { "brainpoolP384r1", 384, 0, + { "brainpoolP384r1", 384, 0, NULL, "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123" "acd3a729901d1a71874700133107ec53", "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f" @@ -263,7 +273,7 @@ static const struct "0e4646217791811142820341263c5315" }, - { "brainpoolP512r1", 512, 0, + { "brainpoolP512r1", 512, 0, NULL, "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871" "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3", "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc" @@ -278,7 +288,7 @@ static const struct "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892" }, - { NULL, 0, 0, NULL, NULL, NULL, NULL } + { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL } }; @@ -349,6 +359,22 @@ curve_free (elliptic_curve_t *E) mpi_free (E->n); E->n = NULL; } +/* + * Release a PK object. + */ +static void ecc_pk_free( ECC_public_key *pk ) { + point_free (&pk->Q); + curve_free (&pk->E); +} + +/* + * Release a SK object. + */ +static void ecc_sk_free( ECC_secret_key *sk ) { + point_free (&sk->Q); + curve_free (&sk->E); + mpi_free (sk->d); sk->d = NULL; +} /* * Return a copy of a curve object. @@ -493,6 +519,9 @@ generate_curve (unsigned int nbits, const char *name, curve->G.x = scanval (domain_parms[idx].g_x); curve->G.y = scanval (domain_parms[idx].g_y); curve->G.z = mpi_alloc_set_ui (1); + memset( curve->name_oid, 0, sizeof(curve->name_oid) ); + if( domain_parms[idx].name_oid != NULL ) + memcpy( curve->name_oid, domain_parms[idx].name_oid, domain_parms[idx].name_oid[0]+1 ); return 0; } @@ -521,13 +550,15 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, if (DBG_CIPHER) { - log_mpidump ("ecc generation p", E.p); - log_mpidump ("ecc generation a", E.a); - log_mpidump ("ecc generation b", E.b); - log_mpidump ("ecc generation n", E.n); - log_mpidump ("ecc generation Gx", E.G.x); - log_mpidump ("ecc generation Gy", E.G.y); - log_mpidump ("ecc generation Gz", E.G.z); + log_mpidump ("ecgen curve p", E.p); + log_mpidump ("ecgen curve a", E.a); + log_mpidump ("ecgen curve b", E.b); + log_mpidump ("ecgen curve n", E.n); + log_mpidump ("ecgen curve G.x", E.G.x); + /* log_mpidump ("ecc generation Gy", E.G.y); + log_mpidump ("ecc generation Gz", E.G.z); */ + + log_printf ("ecgen curve OID: [%d] ...%02X %02X\n", E.name_oid[0], E.name_oid[0]>0 ? E.name_oid[E.name_oid[0]-1] : 0, E.name_oid[E.name_oid[0]]); } random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; @@ -545,6 +576,7 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, sk->E.p = mpi_copy (E.p); sk->E.a = mpi_copy (E.a); sk->E.b = mpi_copy (E.b); + memcpy(sk->E.name_oid, E.name_oid, sizeof(E.name_oid)); point_init (&sk->E.G); point_set (&sk->E.G, &E.G); sk->E.n = mpi_copy (E.n); @@ -556,12 +588,12 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, if (g_x && g_y) { if (_gcry_mpi_ec_get_affine (g_x, g_y, &sk->E.G, ctx)) - log_fatal ("ecc generate: Failed to get affine coordinates\n"); + log_fatal ("ecgen: Failed to get affine coordinates\n"); } if (q_x && q_y) { if (_gcry_mpi_ec_get_affine (q_x, q_y, &sk->Q, ctx)) - log_fatal ("ecc generate: Failed to get affine coordinates\n"); + log_fatal ("ecgen: Failed to get affine coordinates\n"); } _gcry_mpi_ec_free (ctx); @@ -571,7 +603,7 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, /* Now we can test our keys (this should never fail!). */ test_keys (sk, nbits - 64); - + return 0; } @@ -615,8 +647,7 @@ test_keys (ECC_secret_key *sk, unsigned int nbits) if (DBG_CIPHER) log_debug ("ECDSA operation: sign, verify ok.\n"); - point_free (&pk.Q); - curve_free (&pk.E); + ecc_pk_free( &pk ); point_free (&R_); mpi_free (s); @@ -849,7 +880,45 @@ verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s) return err; } +/* lookup named curve and fill in internal curve parameters + * returns GPG_ERR_NOT_FOUND for an unknown OID + */ +static int +fill_in_curve( const byte name_oid[], elliptic_curve_t *curve ) { + int i; + const ecc_domain_parms_t *p; + if( name_oid == NULL || name_oid[0] == 0 ) { + log_debug ("ecc OID is malformed\n"); + return GPG_ERR_INV_ARG; + } + + for (i = 0; domain_parms[i].desc; i++) { + p = domain_parms + i; + if( p->name_oid == NULL || p->name_oid[0] != name_oid[0] ) + continue; + if ( memcmp( p->name_oid, name_oid, name_oid[0]+1 )==0 ) + break; + } + + if( ! p->desc ) { + log_debug ("ecc OID is not recognized\n"); + return GPG_ERR_NOT_FOUND; + } + + // TODO: there is no reason why these values are encoded as ASCII v.s. binary + curve->p = scanval (p->p); + curve->a = scanval (p->a); + curve->b = scanval (p->b); + curve->n = scanval (p->n); + curve->G.x = scanval (p->g_x); + curve->G.y = scanval (p->g_y); + curve->G.z = mpi_alloc_set_ui (1); + + if (DBG_CIPHER) + log_debug( "ec filled in curve %s\n", p->desc ); + return 0; +} /********************************************* ************** interface ****************** @@ -889,8 +958,20 @@ ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p) log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); gcry_free (buf); - mpi_free (x); - mpi_free (y); + return result; +} + +static gcry_mpi_t +name_oid_to_mpi( const byte *name_oid ) { + gpg_error_t err; + gcry_mpi_t result; + + if( name_oid == NULL || name_oid[0] == 0 ) + return mpi_new (0); + + err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, name_oid, name_oid[0]+1, NULL); + if (err) + log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); return result; } @@ -953,6 +1034,35 @@ os2ec (mpi_point_t *result, gcry_mpi_t value) return 0; } +static gcry_err_code_t +mpi_to_name_oid( gcry_mpi_t mpi_in, byte name_oid_out[MAX_ECC_OID_LEN] ) { + size_t nbytes; + unsigned char *buf; + gcry_error_t err; + + memset( name_oid_out, 0, MAX_ECC_OID_LEN ); + + nbytes = (mpi_get_nbits (mpi_in)+7)/8; + if( nbytes == 0 ) + return 0; + + buf = gcry_xmalloc (nbytes); + err = gcry_mpi_print (GCRYMPI_FMT_USG, buf, nbytes, &nbytes, mpi_in); + if (err) + { + gcry_free (buf); + return err; + } + if (buf[0]+1 != nbytes || nbytes >= MAX_ECC_OID_LEN) + { + gcry_free (buf); + return GPG_ERR_INV_OBJ; + } + memcpy( name_oid_out, buf, nbytes+1 ); + gcry_free (buf); + + return 0; +} /* Extended version of ecc_generate. */ static gcry_err_code_t @@ -964,6 +1074,7 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, gpg_err_code_t ec; ECC_secret_key sk; gcry_mpi_t g_x, g_y, q_x, q_y; + gcry_mpi_t kek_params = NULL; char *curve_name = NULL; gcry_sexp_t l1; int transient_key = 0; @@ -974,6 +1085,7 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, if (genparms) { + /* Parse the optional "curve" parameter. */ l1 = gcry_sexp_find_token (genparms, "curve", 0); if (l1) @@ -986,10 +1098,30 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, /* Parse the optional transient-key flag. */ l1 = gcry_sexp_find_token (genparms, "transient-key", 0); + if( l1 ) { + const char *s; + s = _gcry_sexp_nth_string (l1, 1); + if( s && strcmp( s, "1" )==0 ) + transient_key = 1; + gcry_sexp_release (l1); + if (DBG_CIPHER) + log_debug( "ecgen 'transient-key' parameter supplied, value=%d\n", transient_key); + } + + /* Parse the "KEK parameters" parameter. */ + l1 = gcry_sexp_find_token (genparms, "kek-params", 0); if (l1) { - transient_key = 1; + kek_params = gcry_sexp_nth_mpi (l1, 1, 0); gcry_sexp_release (l1); + if (!kek_params) { + log_debug( "ecgen failed to parse 'kek-params'\n" ); + return GPG_ERR_INV_OBJ; /* No curve name or value too large. */ + } + if (DBG_CIPHER) { + log_debug( "ecgen 'kek-params' parameter supplied\n" ); + log_mpidump ("ecgen DH kek-param", kek_params); + } } } @@ -1006,16 +1138,20 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, if (ec) return ec; - skey[0] = sk.E.p; - skey[1] = sk.E.a; - skey[2] = sk.E.b; - /* The function ec2os releases g_x and g_y. */ - skey[3] = ec2os (g_x, g_y, sk.E.p); - skey[4] = sk.E.n; - /* The function ec2os releases g_x and g_y. */ - skey[5] = ec2os (q_x, q_y, sk.E.p); - skey[6] = sk.d; - + skey[0] = name_oid_to_mpi( sk.E.name_oid ); // "c", name OID + //if( (ec=fill_in_curve( sk.E.name_oid, &sk.E )) ) + // return ec; + skey[1] = ec2os (q_x, q_y, sk.E.p); /* public key */ // "q", public key, the point + mpi_free (q_x); + mpi_free (q_y); + + if( algo == GCRY_PK_ECDSA ) { + skey[2] = sk.d; + } + else { + skey[2] = (kek_params ? kek_params : mpi_new (0)); // params, the last field in the public key portion + skey[3] = sk.d; + } point_free (&sk.E.G); point_free (&sk.Q); @@ -1024,6 +1160,21 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, if (!*retfactors) return gpg_err_code_from_syserror (); + if (DBG_CIPHER) + { + if( algo == GCRY_PK_ECDSA ) { + log_mpidump ("ecgen DSA c ", skey[0]); + log_mpidump ("ecgen DSA Q ", skey[1]); + log_mpidump ("ecgen DSA d ", skey[2]); + } + else { + log_mpidump ("ecgen DH c ", skey[0]); + log_mpidump ("ecgen DH Q ", skey[1]); + log_mpidump ("ecgen DH p ", skey[2]); + log_mpidump ("ecgen DH d ", skey[3]); + } + } + return 0; } @@ -1036,7 +1187,12 @@ ecc_generate (int algo, unsigned int nbits, unsigned long evalue, return ecc_generate_ext (algo, nbits, 0, NULL, skey, retfactors, NULL); } - +#if 0 +/* Need to be implemented, if called neeeded. The issue is that the purpose of this function is to return the information about + * the curve that is beyond the information present in the public key. In particular, the pkey size is now just 2, + * while we may need to return E.a, E.b, E.p, E.n, E.g, type of the curve, at the minimum. + * This information is readily available for well-known named curves. + */ /* Return the parameters of the curve NAME. */ static gcry_err_code_t ecc_get_param (const char *name, gcry_mpi_t *pkey) @@ -1059,15 +1215,17 @@ ecc_get_param (const char *name, gcry_mpi_t *pkey) _gcry_mpi_ec_free (ctx); point_free (&E.G); - pkey[0] = E.p; - pkey[1] = E.a; - pkey[2] = E.b; - pkey[3] = ec2os (g_x, g_y, E.p); - pkey[4] = E.n; - pkey[5] = NULL; + pkey[0] = name_oid_to_mpi( E.name_oid ); + pkey[1] = E.p; + pkey[2] = E.a; + pkey[3] = E.b; + pkey[4] = ec2os (g_x, g_y, E.p); + pkey[5] = E.n; + pkey[6] = NULL; return 0; } +#endif static gcry_err_code_t @@ -1078,23 +1236,15 @@ ecc_check_secret_key (int algo, gcry_mpi_t *skey) (void)algo; - if (!skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] || !skey[5] - || !skey[6] || !skey[7] || !skey[8] || !skey[9] || !skey[10]) + if (!skey[0] || !skey[1] || !skey[2] ) return GPG_ERR_BAD_MPI; - sk.E.p = skey[0]; - sk.E.a = skey[1]; - sk.E.b = skey[2]; - point_init (&sk.E.G); - err = os2ec (&sk.E.G, skey[3]); - if (err) - { - point_free (&sk.E.G); - return err; - } - sk.E.n = skey[4]; + if( (err=mpi_to_name_oid( skey[0], sk.E.name_oid )) ) + return err; + if( (err=fill_in_curve( sk.E.name_oid, &sk.E )) ) + return err; point_init (&sk.Q); - err = os2ec (&sk.Q, skey[5]); + err = os2ec (&sk.Q, skey[1]); if (err) { point_free (&sk.E.G); @@ -1102,7 +1252,7 @@ ecc_check_secret_key (int algo, gcry_mpi_t *skey) return err; } - sk.d = skey[6]; + sk.d = skey[2]; if (check_secret_key (&sk)) { @@ -1124,30 +1274,22 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey) (void)algo; - if (!data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] - || !skey[5] || !skey[6] ) + if (!data || !skey[0] || !skey[1] || !skey[2] ) return GPG_ERR_BAD_MPI; - sk.E.p = skey[0]; - sk.E.a = skey[1]; - sk.E.b = skey[2]; - point_init (&sk.E.G); - err = os2ec (&sk.E.G, skey[3]); - if (err) - { - point_free (&sk.E.G); - return err; - } - sk.E.n = skey[4]; + if( (err=mpi_to_name_oid( skey[0], sk.E.name_oid )) ) + return err; + if( (err=fill_in_curve( sk.E.name_oid, &sk.E )) ) + return err; point_init (&sk.Q); - err = os2ec (&sk.Q, skey[5]); + err = os2ec (&sk.Q, skey[1]); if (err) { point_free (&sk.E.G); point_free (&sk.Q); return err; } - sk.d = skey[6]; + sk.d = gcry_mpi_copy( skey[2] ); resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.E.p)); resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.E.p)); @@ -1158,8 +1300,7 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey) mpi_free (resarr[1]); resarr[0] = NULL; /* Mark array as released. */ } - point_free (&sk.E.G); - point_free (&sk.Q); + ecc_sk_free( &sk ); return err; } @@ -1174,65 +1315,139 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, (void)cmp; (void)opaquev; - if (!data[0] || !data[1] || !hash || !pkey[0] || !pkey[1] || !pkey[2] - || !pkey[3] || !pkey[4] || !pkey[5] ) + if (!data[0] || !data[1] || !hash || !pkey[0] || !pkey[1] ) return GPG_ERR_BAD_MPI; - pk.E.p = pkey[0]; - pk.E.a = pkey[1]; - pk.E.b = pkey[2]; - point_init (&pk.E.G); - err = os2ec (&pk.E.G, pkey[3]); - if (err) - { - point_free (&pk.E.G); - return err; - } - pk.E.n = pkey[4]; + if( (err=mpi_to_name_oid( pkey[0], pk.E.name_oid )) ) + return err; + if( (err=fill_in_curve( pk.E.name_oid, &pk.E )) ) + return err; point_init (&pk.Q); - err = os2ec (&pk.Q, pkey[5]); + err = os2ec (&pk.Q, pkey[1]); if (err) { - point_free (&pk.E.G); - point_free (&pk.Q); + ecc_pk_free( &pk ); return err; } err = verify (hash, &pk, data[0], data[1]); - point_free (&pk.E.G); - point_free (&pk.Q); + ecc_pk_free( &pk ); return err; } - -static unsigned int -ecc_get_nbits (int algo, gcry_mpi_t *pkey) +/* ecdh is very simple. It is basically the implementation of the primitive operation in the EC field. + * 'data' is scalar, 2-MPI array pkey uniquely defines a point on the curve. + * + * The complexity of ECDH encryption is shifted into OpenPGP layer to keep libgcrypt + * layer generic. ecc_encrypt is identical to ecc_decrypt due to the symmetry of DH protocol. + */ +static gcry_err_code_t +ecc_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey, int flags) { + ECC_secret_key sk; + mpi_point_t R; /* result that we return */ + mpi_ec_t ctx; + gcry_mpi_t result; + int err; + (void)algo; + (void)flags; + + if (DBG_CIPHER) + log_debug ("Called ecc_encrypt data size=%d bits, flags=%08x\n", gcry_mpi_get_nbits (data), flags); + + if ( !data || !pkey[0] || !pkey[1] ) + return GPG_ERR_BAD_MPI; - return mpi_get_nbits (pkey[0]); + if (DBG_CIPHER) + { + log_mpidump ("ecdh encrypt c ", pkey[0]); + log_mpidump ("ecdh encrypt q ", pkey[1]); + log_mpidump ("ecdh encrypt p ", pkey[2]); + log_mpidump ("ecdh encrypt data", data); + } + + if( (err=mpi_to_name_oid( pkey[0], sk.E.name_oid )) ) + return err; + if( (err=fill_in_curve( sk.E.name_oid, &sk.E )) ) + return err; + + point_init (&sk.Q); + err = os2ec (&sk.Q, pkey[1]); + sk.d = gcry_mpi_copy( data ); + if (err) + { + ecc_sk_free( &sk ); + return err; + } + + ctx = _gcry_mpi_ec_init (sk.E.p, sk.E.a); + + point_init (&R); + _gcry_mpi_ec_mul_point (&R, sk.d, &sk.Q, ctx); + + /* the following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */ + { + gcry_mpi_t x,y; + x = mpi_new (0); + y = mpi_new (0); + + if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) + log_fatal ("ecdh: Failed to get affine coordinates\n"); + + result = ec2os( x, y, sk.E.p ); + mpi_free(x); + mpi_free(y); + } + + point_free( &R ); + _gcry_mpi_ec_free (ctx); + ecc_sk_free( &sk ); + + if( result == NULL ) + return GPG_ERR_ENOMEM; + + /* success */ + + resarr[0] = result; + resarr[1] = mpi_new (0); /* not used; it is constructruced at OpenPGP layer */ + + return GPG_ERR_NO_ERROR; } +static gcry_err_code_t +ecc_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data, gcry_mpi_t *skey, int flags) +{ + return ecc_encrypt( algo, result, data[0], skey, flags ); +} +static unsigned int +ecc_get_nbits (int algo, gcry_mpi_t *pkey) +{ + (void)algo; + /* derive it from public key point Q, which is 1 byte + x + y */ + return (mpi_get_nbits (pkey[1]) / (8*2)) * 8; +} /* See rsa.c for a description of this function. */ static gpg_err_code_t compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) { - static const char names[] = "pabgnq"; +#define N_ECC_PUBKEY_COMPONENETS 2 + static const char names[] = "cq"; gpg_err_code_t ec = 0; gcry_sexp_t l1; - gcry_mpi_t values[6]; + gcry_mpi_t values[N_ECC_PUBKEY_COMPONENETS]; int idx; /* Clear the values for easier error cleanup. */ - for (idx=0; idx < 6; idx++) + for (idx=0; idx < sizeof(values)/sizeof(values[0]); idx++) values[idx] = NULL; /* Fill values with all available parameters. */ - for (idx=0; idx < 6; idx++) + for (idx=0; idx < sizeof(values)/sizeof(values[0]); idx++) { l1 = gcry_sexp_find_token (keyparam, names+idx, 1); if (l1) @@ -1246,16 +1461,18 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) } } } - + +#if 0 + /* Not used now: curve name (DER OID of the name, actually) is always hashed above */ /* Check whether a curve parameter is available and use that to fill in missing values. */ l1 = gcry_sexp_find_token (keyparam, "curve", 5); if (l1) { char *curve; - gcry_mpi_t tmpvalues[6]; + gcry_mpi_t tmpvalues[N_ECC_PUBKEY_COMPONENETS]; - for (idx = 0; idx < 6; idx++) + for (idx = 0; idx < sizeof(tmpvalues)/sizeof(tmpvalues[0]); idx++) tmpvalues[idx] = NULL; curve = _gcry_sexp_nth_string (l1, 1); @@ -1269,7 +1486,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) if (ec) goto leave; - for (idx = 0; idx < 6; idx++) + for (idx = 0; idx < sizeof(values)/sizeof(values[0]); idx++) { if (!values[idx]) values[idx] = tmpvalues[idx]; @@ -1277,11 +1494,12 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) mpi_free (tmpvalues[idx]); } } +#endif /* Check that all parameters are known and normalize all MPIs (that should not be required but we use an internal function later and thus we better make 100% sure that they are normalized). */ - for (idx = 0; idx < 6; idx++) + for (idx = 0; idx < sizeof(values)/sizeof(values[0]); idx++) if (!values[idx]) { ec = GPG_ERR_NO_OBJ; @@ -1291,7 +1509,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) _gcry_mpi_normalize (values[idx]); /* Hash them all. */ - for (idx = 0; idx < 6; idx++) + for (idx = 0; idx < sizeof(values)/sizeof(values[0]); idx++) { char buf[30]; unsigned char *rawmpi; @@ -1311,10 +1529,11 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) } leave: - for (idx = 0; idx < 6; idx++) + for (idx = 0; idx < sizeof(values)/sizeof(values[0]); idx++) _gcry_mpi_release (values[idx]); return ec; +#undef N_ECC_PUBKEY_COMPONENETS } @@ -1375,14 +1594,20 @@ run_selftests (int algo, int extended, selftest_report_func_t report) static const char *ecdsa_names[] = { "ecdsa", - "ecc", + "ecdh", + "ecc", // only here, for the minimum number of public parameters (= 2) + NULL, + }; +static const char *ecdh_names[] = + { + "ecdh", NULL, }; gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = { "ECDSA", ecdsa_names, - "pabgnq", "pabgnqd", "", "rs", "pabgnq", + "cq", "cqd", "", "rs", "cq", GCRY_PK_USAGE_SIGN, ecc_generate, ecc_check_secret_key, @@ -1393,11 +1618,26 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = ecc_get_nbits }; +gcry_pk_spec_t _gcry_pubkey_spec_ecdh = + { + "ECDH", ecdh_names, + "cqp", "cqpd", "ab", "", "cqp", + GCRY_PK_USAGE_ENCR, + ecc_generate, + ecc_check_secret_key, + ecc_encrypt, + ecc_decrypt, + NULL, + NULL, + ecc_get_nbits + }; + + pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = { run_selftests, ecc_generate_ext, compute_keygrip, - ecc_get_param + NULL // ecc_get_param }; diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 86693e8..6f0609c 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -75,6 +75,8 @@ static struct pubkey_table_entry #if USE_ECC { &_gcry_pubkey_spec_ecdsa, &_gcry_pubkey_extraspec_ecdsa, GCRY_PK_ECDSA, 0 }, + { &_gcry_pubkey_spec_ecdh, + &_gcry_pubkey_extraspec_ecdsa, GCRY_PK_ECDH, 0 }, #endif { NULL, 0 }, }; @@ -981,7 +983,7 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, gcry_module_t module; gcry_pk_spec_t *pubkey; pk_extra_spec_t *extraspec; - int is_ecc; +// int is_ecc; /* Check that the first element is valid. */ list = gcry_sexp_find_token (sexp, @@ -1009,7 +1011,7 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, with a key is compatible with an application of the key (signing, encryption). For RSA this is easy, but ECC is the first algorithm which has many flavours. */ - is_ecc = ( !strcmp (name, "ecdsa") || !strcmp (name, "ecc") ); +// is_ecc = ( !strcmp (name, "ecdsa") || !strcmp (name, "ecc") ); gcry_free (name); if (!module) @@ -1029,9 +1031,9 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, err = gpg_err_code_from_errno (errno); if (!err) { - if (is_ecc) - err = sexp_elements_extract_ecc (list, elems, array, extraspec); - else + // if (is_ecc) + // err = sexp_elements_extract_ecc (list, elems, array, extraspec); + // else err = sexp_elements_extract (list, elems, array, pubkey->name); } diff --git a/configure.ac b/configure.ac index c6bff37..b7fa853 100644 --- a/configure.ac +++ b/configure.ac @@ -26,7 +26,7 @@ min_automake_version="1.10" # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [1.5.0]) +m4_define([my_version], [1.6.0]) m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([printf "%d" $(svn info 2>/dev/null \ diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 883de4a..663ca5e 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -2736,10 +2736,10 @@ are allowed. When specifying Q all values of N in the range 512 to 15680 are valid as long as they are multiples of 8. @item transient-key -This is only meaningful for RSA, DSA and ECDSA keys. This is a flag +This is only meaningful for RSA, DSA, ECDSA, and ECDH keys. This is a flag with no value. If given the key is created using a faster and a somewhat less secure random number generator. This flag may be used for -keys which are only used for a short time and do not require full +keys which are only used for a short time or per-message and do not require full cryptographic strength. @item domain diff --git a/src/cipher.h b/src/cipher.h index 48baab4..2be8787 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -129,6 +129,7 @@ extern gcry_pk_spec_t _gcry_pubkey_spec_rsa; extern gcry_pk_spec_t _gcry_pubkey_spec_elg; extern gcry_pk_spec_t _gcry_pubkey_spec_dsa; extern gcry_pk_spec_t _gcry_pubkey_spec_ecdsa; +extern gcry_pk_spec_t _gcry_pubkey_spec_ecdh; extern pk_extra_spec_t _gcry_pubkey_extraspec_rsa; extern pk_extra_spec_t _gcry_pubkey_extraspec_dsa; ----------------------------------------------------------------------- hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Fri Jan 7 01:03:57 2011 From: cvs at cvs.gnupg.org (by Andrey Jivsov) Date: Fri, 07 Jan 2011 01:03:57 +0100 Subject: [git] GnuPG - branch, ECC-INTEGRATION-2-1, updated. gnupg-2.1.0beta1-33-gded546b Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, ECC-INTEGRATION-2-1 has been updated via ded546b4b5cc2caafa654d94ac8f69a23960427e (commit) from e0972d3d962548972872d889b362560e499340d1 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit ded546b4b5cc2caafa654d94ac8f69a23960427e Author: Andrey Jivsov Date: Thu Jan 6 15:44:01 2011 -0800 Milestone: Data signing/verification and key signing/verification work with ECDSA. diff --git a/configure.ac b/configure.ac index 12545e2..575c1ec 100644 --- a/configure.ac +++ b/configure.ac @@ -1466,7 +1466,7 @@ AC_ARG_ENABLE(optimization, AC_HELP_STRING([--disable-optimization], [disable compiler optimization]), [if test $enableval = no ; then - CFLAGS=`echo $CFLAGS | sed s%-O[[1-9]]%-O0\ %g` + CFLAGS=`echo $CFLAGS | sed s/-O[[1-9]]\ /-O0\ /g` fi]) # diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 42d680a..d43ab2c 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -967,7 +967,7 @@ parse_pubkeyenc (IOBUF inp, int pkttype, unsigned long pktlen, es_fprintf (listfp, "\tdata: "); mpi_print(listfp, k->data[0], mpi_print_mode ); es_putc ('\n', listfp); - es_fprintf (listfp, "\tdata: [% 3d bytes] ", encr_buf[0]); + es_fprintf (listfp, "\tdata: [% 3d bytes] ", encr_buf[0]+1); mpi_print(listfp, k->data[1], mpi_print_mode ); es_putc ('\n', listfp); } ----------------------------------------------------------------------- Summary of changes: configure.ac | 2 +- g10/parse-packet.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Fri Jan 7 14:19:59 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Fri, 07 Jan 2011 14:19:59 +0100 Subject: [git] GPGME - branch, master, updated. gpgme-1.1.8-160-g3a7058c Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "GnuPG Made Easy". The branch, master has been updated via 3a7058cade6caec7ec38ca4b2a8c1826e6df6bb1 (commit) via b3f04d033b7a154b618fb84005272eb44361c508 (commit) from 1feea0961956d9ac4db43756fce0f2acf7442e13 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 3a7058cade6caec7ec38ca4b2a8c1826e6df6bb1 Author: Werner Koch Date: Fri Jan 7 13:53:26 2011 +0100 Typo fixes spotted by Daiki Ueno. diff --git a/doc/gpgme.texi b/doc/gpgme.texi index d8891ea..c9bb708 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -2839,7 +2839,7 @@ The function returns the error code @code{GPG_ERR_INV_VALUE} if @end deftypefun @deftypefun gpgme_error_t gpgme_op_keylist_end (@w{gpgme_ctx_t @var{ctx}}) -The function @code{gpgme_op_keylist_next} ends a pending key list +The function @code{gpgme_op_keylist_end} ends a pending key list operation in the context @var{ctx}. After the operation completed successfully, the result of the key @@ -3914,7 +3914,7 @@ there is not enough memory for the operation. @end deftypefun @deftypefun gpgme_error_t gpgme_op_trustlist_end (@w{gpgme_ctx_t @var{ctx}}) -The function @code{gpgme_op_trustlist_next} ends a pending key list +The function @code{gpgme_op_trustlist_end} ends a pending trust list operation in the context @var{ctx}. The function returns the error code @code{GPG_ERR_INV_VALUE} if commit b3f04d033b7a154b618fb84005272eb44361c508 Author: Werner Koch Date: Fri Jan 7 13:52:31 2011 +0100 Typo fixes. Spotted by Daiki Ueno. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0b336ea --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/aclocal.m4 +/autom4te.cache +/config.h.in +/configure +Makefile.in ----------------------------------------------------------------------- Summary of changes: .gitignore | 5 +++++ doc/gpgme.texi | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .gitignore hooks/post-receive -- GnuPG Made Easy http://git.gnupg.org From cvs at cvs.gnupg.org Fri Jan 7 14:26:27 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Fri, 07 Jan 2011 14:26:27 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.4.4-50-g3bbd874 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 3bbd874e677c5330b93591c3ae38f9e9372ebcd5 (commit) from de7bd128995c9cf6e471d1bb16cf4a2f80262c96 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 3bbd874e677c5330b93591c3ae38f9e9372ebcd5 Author: Werner Koch Date: Fri Jan 7 14:06:27 2011 +0100 Add a list of files to ignore. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..05033b3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +/aclocal.m4 +/autom4te.cache +/config.h.in +/configure +Makefile.in +doc/gcrypt.info +doc/stamp-vti +doc/version.texi ----------------------------------------------------------------------- Summary of changes: .gitignore | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) create mode 100644 .gitignore hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jan 10 11:58:53 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 10 Jan 2011 11:58:53 +0100 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta1-31-g2732f2f Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, master has been updated via 2732f2ff3f44a5aae969d5ce16a4de74478576a2 (commit) from 7d24ffaf805074fce14fed0b22e413cf5ca00024 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 2732f2ff3f44a5aae969d5ce16a4de74478576a2 Author: Werner Koch Date: Mon Jan 10 11:37:57 2011 +0100 Fix bug #1311. diff --git a/NEWS b/NEWS index 2cdf854..2153733 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,9 @@ Noteworthy changes in version 2.1.0beta2 (unreleased) * Fixed CRL loading under W32 (bug#1010). + * Fixed TTY management for pinentries and session variable update + problem. + Noteworthy changes in version 2.1.0beta1 (2010-10-26) ----------------------------------------------------- diff --git a/common/ChangeLog b/common/ChangeLog index de96b8d..6a6f6e0 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,8 @@ +2011-01-10 Werner Koch + + * session-env.c (update_var): Fix same value detection. Fixes + bug#1311. + 2010-12-17 Werner Koch * asshelp.c (lock_spawning): Add arg VERBOSE. Improve timeout diff --git a/common/session-env.c b/common/session-env.c index 2dcf425..d719a7b 100644 --- a/common/session-env.c +++ b/common/session-env.c @@ -183,10 +183,11 @@ update_var (session_env_t se, const char *string, size_t namelen, else if (!strncmp (se->array[idx]->name, string, namelen) && strlen (se->array[idx]->name) == namelen) { - /* Check if the value is the same; no need to update it, - except for updating the default flag. */ if (strlen (se->array[idx]->value) == valuelen) { + /* The new value has the same length. We can update it + in-place. */ + memcpy (se->array[idx]->value, value, valuelen); se->array[idx]->is_default = !!set_default; return 0; } ----------------------------------------------------------------------- Summary of changes: NEWS | 3 +++ common/ChangeLog | 5 +++++ common/session-env.c | 5 +++-- 3 files changed, 11 insertions(+), 2 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jan 10 15:38:48 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 10 Jan 2011 15:38:48 +0100 Subject: [git] GnuPG - branch, STABLE-BRANCH-2-0, updated. gnupg-2.0.16-18-g344d72b Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, STABLE-BRANCH-2-0 has been updated via 344d72b2f7caaa217941adc8cdb70e722ed8f888 (commit) via fc959326b575dd07ea0a1c6686ec93a07d280cd4 (commit) from 46ef7f624393bd7765174a1f2f321d6ac5a41c02 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 344d72b2f7caaa217941adc8cdb70e722ed8f888 Author: Werner Koch Date: Mon Jan 10 15:18:09 2011 +0100 Support a git revision string diff --git a/ChangeLog b/ChangeLog index c35ea42..99d158a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-01-10 Werner Koch + + * configure.ac: Support a git_revision string. + 2010-07-19 Werner Koch Release 2.0.16. diff --git a/configure.ac b/configure.ac index 1332bc5..bf1b39f 100644 --- a/configure.ac +++ b/configure.ac @@ -29,8 +29,11 @@ m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([printf "%d" $(svn info 2>/dev/null \ | sed -n '/^Revision:/ s/[^0-9]//gp'|head -1)])) +m4_define([git_revision], m4_esyscmd([git branch -v 2>/dev/null \ + | awk '/^\* / {printf "%s",$3}'])) AC_INIT([gnupg], - [my_version[]m4_if(my_issvn,[yes],[-svn[]svn_revision])], + [my_version[]m4_if(my_issvn,[yes], + [m4_if(git_revision,[],[-svn[]svn_revision],[-git[]git_revision])])], [http://bugs.gnupg.org]) # Set development_version to yes if the minor number is odd or you # feel that the default check for a development version is not commit fc959326b575dd07ea0a1c6686ec93a07d280cd4 Author: Werner Koch Date: Mon Jan 10 15:16:07 2011 +0100 Fix bug#1311 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..04335fa --- /dev/null +++ b/.gitignore @@ -0,0 +1,135 @@ +Makefile.in +aclocal.m4 +autom4te.cache/ +configure +config.h.in +config.h +config.log +config.status +common/audit-events.h +common/status-codes.h +doc/gnupg.info* +doc/stamp-vti +doc/version.texi +po/gnupg2.pot +po/POTFILES +stamp-h1 +Makefile +.deps/ +keyserver/gpg2keys_mailto +keyserver/gpg2keys_test +tools/gpg-zip + +# Files created by make when not using a VPATH build +*.o +po/en at boldquot.insert-header +po/en at boldquot.po +po/en at quot.insert-header +po/en at quot.po +po/stamp-po +agent/gpg-agent +agent/gpg-preset-passphrase +agent/gpg-protect-tool +agent/t-protect +common/libcommon.a +common/libcommonpth.a +common/libgpgrl.a +common/libsimple-pwquery.a +common/t-b64 +common/t-convert +common/t-exechelp +common/t-gettime +common/t-helpfile +common/t-percent +common/t-session-env +common/t-sexputil +common/t-sysutils +doc/FAQ +doc/addgnupghome.8 +doc/applygnupgdefaults.8 +doc/faq.html +doc/faq.raw.xref +doc/gnupg-card-architecture.eps +doc/gnupg-card-architecture.pdf +doc/gnupg-card-architecture.png +doc/gnupg.7 +doc/gpg-agent.1 +doc/gpg-connect-agent.1 +doc/gpg-preset-passphrase.1 +doc/gpg-zip.1 +doc/gpg2.1 +doc/gpgconf.1 +doc/gpgparsemail.1 +doc/gpgsm-gencert.sh.1 +doc/gpgsm.1 +doc/gpgv2.1 +doc/scdaemon.1 +doc/symcryptrun.1 +doc/watchgnupg.1 +doc/yat2m +doc/yat2m-stamp +g10/gpg2 +g10/gpgv2 +g10/t-rmd160 +gl/alloca.h +gl/libgnu.a +jnlib/libjnlib.a +jnlib/t-stringhelp +kbx/kbxutil +kbx/libkeybox.a +keyserver/gpg2keys_curl +keyserver/gpg2keys_finger +keyserver/gpg2keys_hkp +keyserver/gpg2keys_kdns +keyserver/gpg2keys_ldap +scd/gnupg-pcsc-wrapper +scd/scdaemon +sm/gpgsm +tests/asschk +tests/gpg-agent.conf +tests/gpgsm.conf +tests/inittests.stamp +tests/openpgp/data-32000 +tests/openpgp/data-500 +tests/openpgp/data-80000 +tests/openpgp/data-9000 +tests/openpgp/gpg-agent.conf +tests/openpgp/gpg_dearmor +tests/openpgp/plain-1 +tests/openpgp/plain-2 +tests/openpgp/plain-3 +tests/openpgp/plain-large +tests/openpgp/prepared.stamp +tests/openpgp/pubring.gpg +tests/openpgp/pubring.pkr +tests/openpgp/secring.gpg +tests/openpgp/secring.skr +tests/pkits/ReadMe.txt +tests/pkits/certpairs/ +tests/pkits/certs/ +tests/pkits/crls/ +tests/pkits/gpg-agent.conf +tests/pkits/gpgsm.conf +tests/pkits/inittests.stamp +tests/pkits/pkcs12/ +tests/pkits/pkits.ldif +tests/pkits/pkits.schema +tests/pkits/policies.txt +tests/pkits/smime/ +tests/pkits/testdir.stamp +tests/pkits/trustlist.txt +tests/private-keys-v1.d/ +tests/pubring.kbx +tests/testdir.stamp +tests/trustlist.txt +tools/clean-sat +tools/gpg-check-pattern +tools/gpg-connect-agent +tools/gpgconf +tools/gpgkey2ssh +tools/gpgparsemail +tools/gpgsplit +tools/make-dns-cert +tools/mk-tdata +tools/symcryptrun +tools/watchgnupg diff --git a/NEWS b/NEWS index 8e3ff65..97ba097 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,9 @@ Noteworthy changes in version 2.0.17 (unreleased) * Fixed a bug where Scdaemon sends a signal to Gpg-agent running in non-daemon mode. + * Fixed TTY management for pinentries and session variable update + problem. + Noteworthy changes in version 2.0.16 (2010-07-19) ------------------------------------------------- diff --git a/common/ChangeLog b/common/ChangeLog index c0f618e..9c18680 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,8 @@ +2011-01-10 Werner Koch + + * session-env.c (update_var): Fix same value test. Fixes + bug#1311. + 2010-09-16 Werner Koch * util.h: Add GPG_ERR_MISSING_ISSUER_CERT. diff --git a/common/session-env.c b/common/session-env.c index ef36dbc..10f5dfe 100644 --- a/common/session-env.c +++ b/common/session-env.c @@ -183,10 +183,11 @@ update_var (session_env_t se, const char *string, size_t namelen, else if (!strncmp (se->array[idx]->name, string, namelen) && strlen (se->array[idx]->name) == namelen) { - /* Check if the value is the same; no need to update it, - except for updating the default flag. */ if (strlen (se->array[idx]->value) == valuelen) { + /* The new value has the same length. We can update it + in-place. */ + memcpy (se->array[idx]->value, value, valuelen); se->array[idx]->is_default = !!set_default; return 0; } ----------------------------------------------------------------------- Summary of changes: .gitignore | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++ ChangeLog | 4 ++ NEWS | 3 + common/ChangeLog | 5 ++ common/session-env.c | 5 +- configure.ac | 5 ++- 6 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 .gitignore hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jan 10 16:15:04 2011 From: cvs at cvs.gnupg.org (by Andre Heinecke) Date: Mon, 10 Jan 2011 16:15:04 +0100 Subject: [git] Wincetools - branch, kdepimcetools, updated. d84cefe449bad56464449b8ac23cb03d2eace6e2 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "UNNAMED PROJECT". The branch, kdepimcetools has been updated via d84cefe449bad56464449b8ac23cb03d2eace6e2 (commit) from 01526ee642854a42966d4000c9e7739dbd7bc230 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit d84cefe449bad56464449b8ac23cb03d2eace6e2 Author: Andre Heinecke Date: Mon Jan 10 14:55:05 2011 +0000 Replace splashscreen with the one without loading According to Bernhard there should not be loading on the Splashscreen on WinCE since we have the Wait Cursor already indicating that. diff --git a/loader/splashscreen/splashscreenstatic.bmp b/loader/splashscreen/splashscreenstatic.bmp index 4be8169..ddb4650 100644 Binary files a/loader/splashscreen/splashscreenstatic.bmp and b/loader/splashscreen/splashscreenstatic.bmp differ ----------------------------------------------------------------------- Summary of changes: loader/splashscreen/splashscreenstatic.bmp | Bin 768070 -> 768070 bytes 1 files changed, 0 insertions(+), 0 deletions(-) hooks/post-receive -- UNNAMED PROJECT http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jan 10 19:54:23 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 10 Jan 2011 19:54:23 +0100 Subject: [git] GnuPG - branch, STABLE-BRANCH-2-0, updated. gnupg-2.0.16-19-g18936a1 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, STABLE-BRANCH-2-0 has been updated via 18936a1970aeafd64cbf7b04d8622b331b872818 (commit) from 344d72b2f7caaa217941adc8cdb70e722ed8f888 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 18936a1970aeafd64cbf7b04d8622b331b872818 Author: Werner Koch Date: Mon Jan 10 19:35:10 2011 +0100 Fix bug#1307. diff --git a/common/ChangeLog b/common/ChangeLog index 9c18680..84843cd 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,9 @@ +2011-01-10 Thomas Mraz (wk) + + * pka.c (get_pka_info) [!USE_ADNS]: Turn ANSWER into a union to + avoid aliasing problems with modern compilers. See bug#1307. + Reported by Steve Grubb. + 2011-01-10 Werner Koch * session-env.c (update_var): Fix same value test. Fixes diff --git a/common/pka.c b/common/pka.c index 3d68802..b1247f6 100644 --- a/common/pka.c +++ b/common/pka.c @@ -173,7 +173,11 @@ get_pka_info (const char *address, unsigned char *fpr) return buffer; #else /*!USE_ADNS*/ - unsigned char answer[PACKETSZ]; + union + { + signed char p[PACKETSZ]; + HEADER h; + } answer; int anslen; int qdcount, ancount, nscount, arcount; int rc; @@ -192,11 +196,11 @@ get_pka_info (const char *address, unsigned char *fpr) memcpy (name, address, domain - address); strcpy (stpcpy (name + (domain-address), "._pka."), domain+1); - anslen = res_query (name, C_IN, T_TXT, answer, PACKETSZ); + anslen = res_query (name, C_IN, T_TXT, answer.p, PACKETSZ); xfree (name); if (anslen < sizeof(HEADER)) return NULL; /* DNS resolver returned a too short answer. */ - if ( (rc=((HEADER*)answer)->rcode) != NOERROR ) + if ( (rc=answer.h.rcode) != NOERROR ) return NULL; /* DNS resolver returned an error. */ /* We assume that PACKETSZ is large enough and don't do dynmically @@ -204,16 +208,16 @@ get_pka_info (const char *address, unsigned char *fpr) if (anslen > PACKETSZ) return NULL; /* DNS resolver returned a too long answer */ - qdcount = ntohs (((HEADER*)answer)->qdcount); - ancount = ntohs (((HEADER*)answer)->ancount); - nscount = ntohs (((HEADER*)answer)->nscount); - arcount = ntohs (((HEADER*)answer)->arcount); + qdcount = ntohs (answer.h.qdcount); + ancount = ntohs (answer.h.ancount); + nscount = ntohs (answer.h.nscount); + arcount = ntohs (answer.h.arcount); if (!ancount) return NULL; /* Got no answer. */ - p = answer + sizeof (HEADER); - pend = answer + anslen; /* Actually points directly behind the buffer. */ + p = answer.p + sizeof (HEADER); + pend = answer.p + anslen; /* Actually points directly behind the buffer. */ while (qdcount-- && p < pend) { diff --git a/g10/ChangeLog b/g10/ChangeLog index 7e09fb7..92bfde6 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,14 @@ +2011-01-10 Werner Koch + + * keygen.c (ask_user_id): Fix duplicate test for AMAIL by correct + ANAME. See bug#1307. Reported by Steve Grubb. + + * import.c (import_keys_internal): Make loop code a bit more + readable. See bug#1307. Reported by Steve Grubb. + + * sign.c (sign_file): Fix TEMP_HASHLEN computation. See bug#1307. + Reported by Steve Grubb. + 2010-10-29 David Shaw * pkclist.c (select_algo_from_prefs): Make sure the scores can't diff --git a/g10/import.c b/g10/import.c index e2d77b0..ba2439d 100644 --- a/g10/import.c +++ b/g10/import.c @@ -175,10 +175,9 @@ import_keys_internal( IOBUF inp, char **fnames, int nnames, rc = import( inp, "[stream]", stats, fpr, fpr_len, options); } else { - if( !fnames && !nnames ) - nnames = 1; /* Ohh what a ugly hack to jump into the loop */ + int once = (!fnames && !nnames); - for(i=0; i < nnames; i++ ) { + for(i=0; once || i < nnames; once=0, i++ ) { const char *fname = fnames? fnames[i] : NULL; IOBUF inp2 = iobuf_open(fname); if( !fname ) @@ -201,8 +200,6 @@ import_keys_internal( IOBUF inp, char **fnames, int nnames, log_error("import from `%s' failed: %s\n", fname, g10_errstr(rc) ); } - if( !fname ) - break; } } if (!stats_handle) { diff --git a/g10/keygen.c b/g10/keygen.c index 3aaae9c..8c3e9f6 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -2247,7 +2247,7 @@ ask_user_id (int mode, KBNODE keyblock) xfree(answer); } xfree(answer); - if( !amail && !acomment && !amail ) + if( !aname && !acomment && !amail ) break; xfree(uid); uid = NULL; } diff --git a/g10/sign.c b/g10/sign.c index f54e0d9..94e107c 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -867,8 +867,8 @@ sign_file( strlist_t filenames, int detached, strlist_t locusr, { if (sk_rover->sk->pubkey_algo == PUBKEY_ALGO_DSA) { - int temp_hashlen = gcry_mpi_get_nbits - (sk_rover->sk->skey[1])+7/8; + int temp_hashlen = (gcry_mpi_get_nbits + (sk_rover->sk->skey[1])+7)/8; /* Pick a hash that is large enough for our largest q */ ----------------------------------------------------------------------- Summary of changes: common/ChangeLog | 6 ++++++ common/pka.c | 22 +++++++++++++--------- g10/ChangeLog | 11 +++++++++++ g10/import.c | 7 ++----- g10/keygen.c | 2 +- g10/sign.c | 4 ++-- 6 files changed, 35 insertions(+), 17 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Tue Jan 11 05:31:35 2011 From: cvs at cvs.gnupg.org (by Andrey Jivsov) Date: Tue, 11 Jan 2011 05:31:35 +0100 Subject: [git] GCRYPT - branch, ECC-INTEGRATION-1-5, updated. libgcrypt-1.4.4-51-g8993868 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, ECC-INTEGRATION-1-5 has been updated via 899386826c85f1e757e75bcc5d5b2159d05676a0 (commit) from 2c32b631acc1637c1d7826bcdcecf6c0ae9ce7fc (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 899386826c85f1e757e75bcc5d5b2159d05676a0 Author: Andrey Jivsov Date: Mon Jan 10 20:11:54 2011 -0800 'g10/gpg2 --encrypt --debug 15 -r ecdsa -a -o _e.asc _' and 'g10/gpg2 --debug 15 _e.asc', as well as decoding of an old message posted on https://sites.google.com/site/brainhub/pgpecckeys work. This is the milestone 2 that brings in ECDH support from http://code.google.com/p/gnupg-ecc/source/detail?r=15 . Updated the ECDH code to work with latest gnupg that doesn't expose private components of a public key. diff --git a/cipher/ecc.c b/cipher/ecc.c index fdcbb4c..f33cc1c 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -1337,36 +1337,61 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, } -/* ecdh is very simple. It is basically the implementation of the primitive operation in the EC field. - * 'data' is scalar, 2-MPI array pkey uniquely defines a point on the curve. +/* ecdh raw is classic 2-round DH protocol published in 1976. + * Some overloading is needed to fit it to encrypt/decrypt PK interface of libgcrypt. + * + * The only need for this complexity is that some designs of client of libgcrypt + * don't allow to get the private components of public keys. * - * The complexity of ECDH encryption is shifted into OpenPGP layer to keep libgcrypt - * layer generic. ecc_encrypt is identical to ecc_decrypt due to the symmetry of DH protocol. + * Overview of ecc_encrypt_raw and ecc_decrypt_raw. + * + * As with any PK operation, encrypt version uses a public key and decrypt -- private. + * + * Symbols used bellow: + * G - field generator point + * x - private long-term scalar + * xG - public long-term key + * k - ephemeral scalar + * kG - ephemeral public key + * xkG - shared secret + * + * ecc_encrypt_raw description: + * input: + * data[0] : private scalar (k) + * output: + * resaddr[0] : shared point (k*x*G, where x is the secret scalar of pkey; it's the shared secret) + * resaddr[1] : generated ephemeral public key (kG) + * + * ecc_decrypt_raw description: + * input: + * data[0] : a point kG (ephemeral public key) + * output: + * result[0] : shared point (k*x*G, where x is the secret scalar of pkey; it's the shared secret) */ static gcry_err_code_t -ecc_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey, int flags) +ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey, int flags) { ECC_secret_key sk; - mpi_point_t R; /* result that we return */ mpi_ec_t ctx; - gcry_mpi_t result; + gcry_mpi_t result[2]; + mpi_point_t eph_Q; int err; (void)algo; (void)flags; if (DBG_CIPHER) - log_debug ("Called ecc_encrypt data size=%d bits, flags=%08x\n", gcry_mpi_get_nbits (data), flags); + log_debug ("Called ecc_encrypt_raw data size=%d bits, flags=%08x\n", gcry_mpi_get_nbits (data), flags); if ( !data || !pkey[0] || !pkey[1] ) return GPG_ERR_BAD_MPI; if (DBG_CIPHER) { - log_mpidump ("ecdh encrypt c ", pkey[0]); - log_mpidump ("ecdh encrypt q ", pkey[1]); - log_mpidump ("ecdh encrypt p ", pkey[2]); - log_mpidump ("ecdh encrypt data", data); + log_mpidump ("ecdh encrypt PK c ", pkey[0]); + log_mpidump ("ecdh encrypt PK q ", pkey[1]); + log_mpidump ("ecdh encrypt PK p ", pkey[2]); + log_mpidump ("ecdh encrypt data k", data); } if( (err=mpi_to_name_oid( pkey[0], sk.E.name_oid )) ) @@ -1385,6 +1410,108 @@ ecc_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey, in ctx = _gcry_mpi_ec_init (sk.E.p, sk.E.a); + + /* the following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */ + { + mpi_point_t R; /* result that we return */ + gcry_mpi_t x,y; + + x = mpi_new (0); + y = mpi_new (0); + + point_init (&R); + + _gcry_mpi_ec_mul_point (&R, sk.d, &sk.Q, ctx); + + if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) + log_fatal ("ecdh: Failed to get affine coordinates for xkG\n"); + + result[0] = ec2os( x, y, sk.E.p ); /* xkG */ + + _gcry_mpi_ec_mul_point (&R, sk.d, &sk.E.G, ctx); + + if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) + log_fatal ("ecdh: Failed to get affine coordinates for kG\n"); + + result[1] = ec2os( x, y, sk.E.p ); /* kG */ + + mpi_free(x); + mpi_free(y); + + point_free( &R ); + } + + _gcry_mpi_ec_free (ctx); + ecc_sk_free( &sk ); + + if( result[0] == NULL || result[1] == NULL ) { + mpi_free( result[0] ); + mpi_free( result[1] ); + return GPG_ERR_ENOMEM; + } + + /* success */ + + /* none of 2 returned values are used as is; they are further processed at OpenPGP layer. + * However, they match the number of MPIs (2) needed to encrypt a message in OpenPGP format + */ + resarr[0] = result[0]; + resarr[1] = result[1]; + + return GPG_ERR_NO_ERROR; +} + + /* input: + * data[0] : a point kG (ephemeral public key) + * output: + * resaddr[0] : shared point k*x*G + * + * see ecc_encrypt_raw for details. + */ +static gcry_err_code_t +ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, gcry_mpi_t *skey, int flags) +{ + ECC_secret_key sk; + mpi_point_t R; /* result that we return */ + mpi_ec_t ctx; + gcry_mpi_t r; + int err; + + (void)algo; + (void)flags; + + *result = NULL; + + if (DBG_CIPHER) + log_debug ("Called ecc_encrypt_raw data size=%d bits, flags=%08x\n", gcry_mpi_get_nbits (data), flags); + + if ( !data || !data[0] || !skey[0] || !skey[1] || !skey[3] ) + return GPG_ERR_BAD_MPI; + + if (DBG_CIPHER) + { + log_mpidump ("ecdh decrypt SK c ", skey[0]); + log_mpidump ("ecdh decrypt SK q ", skey[1]); + log_mpidump ("ecdh decrypt SK p ", skey[2]); + log_mpidump ("ecdh decrypt data kG", data[0]); + } + + if( (err=mpi_to_name_oid( skey[0], sk.E.name_oid )) ) + return err; + if( (err=fill_in_curve( sk.E.name_oid, &sk.E )) ) + return err; + + point_init (&sk.Q); + err = os2ec (&sk.Q, data[0]); + sk.d = gcry_mpi_copy( skey[3] ); + if (err) + { + ecc_sk_free( &sk ); + return err; + } + + ctx = _gcry_mpi_ec_init (sk.E.p, sk.E.a); + point_init (&R); _gcry_mpi_ec_mul_point (&R, sk.d, &sk.Q, ctx); @@ -1397,7 +1524,7 @@ ecc_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey, in if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) log_fatal ("ecdh: Failed to get affine coordinates\n"); - result = ec2os( x, y, sk.E.p ); + r = ec2os( x, y, sk.E.p ); mpi_free(x); mpi_free(y); } @@ -1406,23 +1533,16 @@ ecc_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey, in _gcry_mpi_ec_free (ctx); ecc_sk_free( &sk ); - if( result == NULL ) + if( r == NULL ) return GPG_ERR_ENOMEM; /* success */ - resarr[0] = result; - resarr[1] = mpi_new (0); /* not used; it is constructruced at OpenPGP layer */ + *result = r; return GPG_ERR_NO_ERROR; } -static gcry_err_code_t -ecc_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data, gcry_mpi_t *skey, int flags) -{ - return ecc_encrypt( algo, result, data[0], skey, flags ); -} - static unsigned int ecc_get_nbits (int algo, gcry_mpi_t *pkey) { @@ -1625,8 +1745,8 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdh = GCRY_PK_USAGE_ENCR, ecc_generate, ecc_check_secret_key, - ecc_encrypt, - ecc_decrypt, + ecc_encrypt_raw, + ecc_decrypt_raw, NULL, NULL, ecc_get_nbits ----------------------------------------------------------------------- Summary of changes: cipher/ecc.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 144 insertions(+), 24 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Tue Jan 11 05:43:51 2011 From: cvs at cvs.gnupg.org (by Andrey Jivsov) Date: Tue, 11 Jan 2011 05:43:51 +0100 Subject: [git] GnuPG - branch, ECC-INTEGRATION-2-1, updated. gnupg-2.1.0beta1-35-g5761a9b Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, ECC-INTEGRATION-2-1 has been updated via 5761a9ba74e41f52660e20a1de700fe784c97832 (commit) via b0c55d08a8c835fd58d3c0d1f9f412b74c1b5678 (commit) from ded546b4b5cc2caafa654d94ac8f69a23960427e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 5761a9ba74e41f52660e20a1de700fe784c97832 Author: Andrey Jivsov Date: Mon Jan 10 20:24:14 2011 -0800 'g10/gpg2 --encrypt --debug 15 -r ecdsa -a -o _e.asc _' and 'g10/gpg2 --debug 15 _e.asc', as well as decoding of an old message posted on https://sites.google.com/site/brainhub/pgpecckeys work. This is the milestone 2 that brings in ECDH support from http://code.google.com/p/gnupg-ecc/source/detail?r=15 . This corresponds to the commit 899386826c85f1e757e75bcc5d5b2159d05676a0 in libgcrypt diff --git a/g10/call-agent.c b/g10/call-agent.c index 25f9a53..dc2ace0 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -1744,7 +1744,6 @@ inq_ciphertext_cb (void *opaque, const char *line) gpg_error_t agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, gcry_sexp_t s_ciphertext, - const byte sk_fp[MAX_FINGERPRINT_LEN], unsigned char **r_buf, size_t *r_buflen) { gpg_error_t err; @@ -1753,8 +1752,6 @@ agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, size_t n, len; char *p, *buf, *endp; - /*TODO: use sk_fp */ - if (!keygrip || strlen(keygrip) != 40 || !s_ciphertext || !r_buf || !r_buflen) return gpg_error (GPG_ERR_INV_VALUE); *r_buf = NULL; diff --git a/g10/call-agent.h b/g10/call-agent.h index 45e593b..e09c309 100644 --- a/g10/call-agent.h +++ b/g10/call-agent.h @@ -168,7 +168,6 @@ gpg_error_t agent_pksign (ctrl_t ctrl, const char *cache_nonce, /* Decrypt a ciphertext. */ gpg_error_t agent_pkdecrypt (ctrl_t ctrl, const char *keygrip, const char *desc, gcry_sexp_t s_ciphertext, - const byte sk_fp[MAX_FINGERPRINT_LEN], unsigned char **r_buf, size_t *r_buflen); /* Retrieve a key encryption key. */ diff --git a/g10/ecdh.c b/g10/ecdh.c index 6615b75..091a28c 100644 --- a/g10/ecdh.c +++ b/g10/ecdh.c @@ -76,8 +76,6 @@ pk_ecdh_default_params_to_mpi( int qbits ) { */ byte * pk_ecdh_default_params( int qbits, size_t *sizeout ) { - gpg_error_t err; - gcry_mpi_t result; /* Defaults are the strongest possible choices. Performance is not an issue here, only interoperability. */ byte kek_params[4] = { 3 /*size of following field*/, @@ -370,6 +368,29 @@ pk_ecdh_encrypt_with_shared_point ( int is_encrypt, gcry_mpi_t shared_mpi, return rc; } + +static gcry_mpi_t +gen_k (unsigned nbits) +{ + gcry_mpi_t k; + + k = gcry_mpi_snew (nbits); + if (DBG_CIPHER) + log_debug ("choosing a random k of %u bits\n", nbits); + + gcry_mpi_randomize (k, nbits-1, GCRY_STRONG_RANDOM); + + if( DBG_CIPHER ) { + unsigned char *buffer; + if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, k)) + BUG (); + log_debug("ephemeral scalar MPI #0: %s\n", buffer); + gcry_free( buffer ); + } + + return k; +} + /* Perform ECDH encryption, which involves ECDH key generation. */ int @@ -377,25 +398,17 @@ pk_ecdh_encrypt (gcry_mpi_t * resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcr { gcry_sexp_t s_ciph, s_data, s_pkey; - PKT_public_key *pk_eph; int nbits; int rc; + gcry_mpi_t k; nbits = pubkey_nbits( PUBKEY_ALGO_ECDH, pkey ); - - /*** Generate an ephemeral key ***/ - rc = pk_ecc_keypair_gen( &pk_eph, PUBKEY_ALGO_ECDH, KEYGEN_FLAG_TRANSIENT_KEY | KEYGEN_FLAG_NO_PROTECTION /*this is ephemeral*/, "", nbits ); - if( rc ) - return rc; - if( DBG_CIPHER ) { - unsigned char *buffer; - if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, pk_eph->pkey[1])) - BUG (); - log_debug("ephemeral key MPI #0: %s\n", buffer); - gcry_free( buffer ); - } - free_public_key (pk_eph); + /*** Generate an ephemeral key, actually, a scalar ***/ + + k = gen_k (nbits); + if( k == NULL ) + BUG (); /*** Done with ephemeral key generation. * Now use ephemeral secret to get the shared secret. ***/ @@ -406,7 +419,7 @@ pk_ecdh_encrypt (gcry_mpi_t * resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcr BUG (); /* put the data into a simple list */ - if (gcry_sexp_build (&s_data, NULL, "%m", pk_eph->pkey[3])) /* ephemeral scalar goes as data */ + if (gcry_sexp_build (&s_data, NULL, "%m", k)) /* ephemeral scalar goes as data */ BUG (); /* pass it to libgcrypt */ @@ -421,7 +434,7 @@ pk_ecdh_encrypt (gcry_mpi_t * resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcr { gcry_mpi_t shared = mpi_from_sexp (s_ciph, "a"); /* ... and get the shared point */ gcry_sexp_release (s_ciph); - resarr[0] = pk_eph->pkey[1]; /* ephemeral public key */ + resarr[0] = mpi_from_sexp (s_ciph, "b"); /* ephemeral public key */ if( DBG_CIPHER ) { unsigned char *buffer; @@ -441,37 +454,10 @@ pk_ecdh_encrypt (gcry_mpi_t * resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcr /* Perform ECDH decryption. */ int -pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t *data, gcry_mpi_t * skey) { - gcry_sexp_t s_skey, s_data, s_ciph; - int rc; - - if (!data[0] || !data[1]) +pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t shared, gcry_mpi_t * skey) { + if (!data) return gpg_error (GPG_ERR_BAD_MPI); - - rc = gcry_sexp_build (&s_skey, NULL, - "(public-key(ecdh(c%m)(q%m)(p%m)))", - skey[0]/*curve*/, data[0]/*ephemeral key*/, skey[2]/*KDF params*/); - if (rc) - BUG (); - - /* put the data into a simple list */ - if (gcry_sexp_build (&s_data, NULL, "%m", skey[3])) /* static private key (scalar) goes as data */ - BUG (); - - rc = gcry_pk_encrypt (&s_ciph, s_data, s_skey); /* encrypting ephemeral key with our private scalar yields the shared point */ - gcry_sexp_release (s_skey); - gcry_sexp_release (s_data); - if (rc) - return rc; - - { - gcry_mpi_t shared = mpi_from_sexp (s_ciph, "a"); /* get the shared point */ - gcry_sexp_release (s_ciph); - rc = pk_ecdh_encrypt_with_shared_point ( 0 /*=decryption*/, shared, sk_fp, data[1]/*encr data as an MPI*/, skey, result ); - mpi_release( shared ); - } - - return rc; + return pk_ecdh_encrypt_with_shared_point ( 0 /*=decryption*/, shared, sk_fp, data/*encr data as an MPI*/, skey, result ); } diff --git a/g10/pkglue.c b/g10/pkglue.c index f785919..9050cc2 100644 --- a/g10/pkglue.c +++ b/g10/pkglue.c @@ -257,80 +257,6 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, const byte pk_fp[MAX return rc; } - - -/**************** - * Emulate our old PK interface here - sometime in the future we might - * change the internal design to directly fit to libgcrypt. - */ -int -pk_decrypt (int algo, gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t * data, - gcry_mpi_t * skey) -{ - gcry_sexp_t s_skey, s_data, s_plain; - int rc; - - *result = NULL; - /* make a sexp from skey */ - if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E) - { - rc = gcry_sexp_build (&s_skey, NULL, - "(private-key(elg(p%m)(g%m)(y%m)(x%m)))", - skey[0], skey[1], skey[2], skey[3]); - } - else if (algo == GCRY_PK_RSA || algo == GCRY_PK_RSA_E) - { - rc = gcry_sexp_build (&s_skey, NULL, - "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))", - skey[0], skey[1], skey[2], skey[3], skey[4], - skey[5]); - } - else if( algo == PUBKEY_ALGO_ECDH ) { - return pk_ecdh_decrypt( result, sk_fp, data, skey ); - } - else - return GPG_ERR_PUBKEY_ALGO; - - if (rc) - BUG (); - - /* put data into a S-Exp s_data */ - if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E) - { - if (!data[0] || !data[1]) - rc = gpg_error (GPG_ERR_BAD_MPI); - else - rc = gcry_sexp_build (&s_data, NULL, - "(enc-val(elg(a%m)(b%m)))", data[0], data[1]); - } - else if (algo == GCRY_PK_RSA || algo == GCRY_PK_RSA_E) - { - if (!data[0]) - rc = gpg_error (GPG_ERR_BAD_MPI); - else - rc = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", data[0]); - } - else - BUG (); - - if (rc) - BUG (); - - rc = gcry_pk_decrypt (&s_plain, s_data, s_skey); - gcry_sexp_release (s_skey); - gcry_sexp_release (s_data); - if (rc) - return rc; - - *result = gcry_sexp_nth_mpi (s_plain, 0, 0); - gcry_sexp_release (s_plain); - if (!*result) - return -1; /* oops */ - - return 0; -} - - /* Check whether SKEY is a suitable secret key. */ int pk_check_secret_key (int algo, gcry_mpi_t *skey) diff --git a/g10/pkglue.h b/g10/pkglue.h index 0d51948..a1c821d 100644 --- a/g10/pkglue.h +++ b/g10/pkglue.h @@ -33,8 +33,8 @@ int pk_decrypt (int algo, gcry_mpi_t *result, const byte fp[MAX_FINGERPRINT_LEN] gcry_mpi_t *skey); int pk_check_secret_key (int algo, gcry_mpi_t *skey); -int pk_ecdh_encrypt (gcry_mpi_t * resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t * pkey); -int pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t *data, gcry_mpi_t * skey); +int pk_ecdh_encrypt (gcry_mpi_t * resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t * pkey); +int pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t shared, gcry_mpi_t * skey); gcry_mpi_t pk_ecdh_default_params_to_mpi( int qbits ); byte *pk_ecdh_default_params( int qbits, size_t *sizeout ); diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index a5224e2..24411e8 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -147,14 +147,16 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) char *keygrip; byte fp[MAX_FINGERPRINT_LEN]; size_t fpn; + const int gcry_pkalgo = map_pk_openpgp_to_gcry( sk->pubkey_algo ); /* Get the keygrip. */ err = hexkeygrip_from_pk (sk, &keygrip); if (err) goto leave; + /* Convert the data to an S-expression. */ - if (sk->pubkey_algo == GCRY_PK_ELG || sk->pubkey_algo == GCRY_PK_ELG_E) + if (gcry_pkalgo == GCRY_PK_ELG ||gcry_pkalgo == GCRY_PK_ELG_E) { if (!enc->data[0] || !enc->data[1]) err = gpg_error (GPG_ERR_BAD_MPI); @@ -162,7 +164,7 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) err = gcry_sexp_build (&s_data, NULL, "(enc-val(elg(a%m)(b%m)))", enc->data[0], enc->data[1]); } - else if (sk->pubkey_algo == GCRY_PK_RSA || sk->pubkey_algo == GCRY_PK_RSA_E) + else if (gcry_pkalgo == GCRY_PK_RSA || gcry_pkalgo == GCRY_PK_RSA_E) { if (!enc->data[0]) err = gpg_error (GPG_ERR_BAD_MPI); @@ -170,6 +172,14 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) err = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", enc->data[0]); } + else if (gcry_pkalgo == GCRY_PK_ECDH ) + { + if (!enc->data[0] || !enc->data[1]) + err = gpg_error (GPG_ERR_BAD_MPI); + else + err = gcry_sexp_build (&s_data, NULL, "(enc-val(ecdh(a%m)(b%m)))", + enc->data[0], enc->data[1]); + } else err = gpg_error (GPG_ERR_BUG); @@ -181,7 +191,7 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) /* Decrypt. */ desc = gpg_format_keydesc (sk, 0, 1); - err = agent_pkdecrypt (NULL, keygrip, desc, s_data, fp, &frame, &nframe); + err = agent_pkdecrypt (NULL, keygrip, desc, s_data, &frame, &nframe); xfree (desc); gcry_sexp_release (s_data); if (err) @@ -233,6 +243,30 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) } } else { + gcry_mpi_t shared_mpi; + gcry_mpi_t decoded; + + /* at the beginning the frame is the bytes of shared point MPI */ + + err = gcry_mpi_scan (&shared_mpi, GCRYMPI_FMT_USG, frame, nframe, NULL); + if (err) { + log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); + goto leave; + } + + err = pk_ecdh_decrypt (&decoded, fp, enc->data[1]/*encr data as an MPI*/, shared_mpi, sk->pkey); + mpi_release( shared_mpi ); + if( err ) + goto leave; + + /* reuse nframe, which size is sufficient to include the session key */ + err = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &nframe, decoded); + mpi_release( decoded ); + if( err ) + goto leave; + + /* Now the frame is the bytes decrypted but padded session key */ + /* Allow double padding for the benefit of DEK size concealment. * Higher than this is wasteful. */ commit b0c55d08a8c835fd58d3c0d1f9f412b74c1b5678 Author: Werner Koch Date: Mon Jan 10 11:37:57 2011 +0100 Fix bug #1311. diff --git a/NEWS b/NEWS index 2cdf854..2153733 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,9 @@ Noteworthy changes in version 2.1.0beta2 (unreleased) * Fixed CRL loading under W32 (bug#1010). + * Fixed TTY management for pinentries and session variable update + problem. + Noteworthy changes in version 2.1.0beta1 (2010-10-26) ----------------------------------------------------- diff --git a/common/ChangeLog b/common/ChangeLog index de96b8d..6a6f6e0 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,8 @@ +2011-01-10 Werner Koch + + * session-env.c (update_var): Fix same value detection. Fixes + bug#1311. + 2010-12-17 Werner Koch * asshelp.c (lock_spawning): Add arg VERBOSE. Improve timeout diff --git a/common/session-env.c b/common/session-env.c index 2dcf425..d719a7b 100644 --- a/common/session-env.c +++ b/common/session-env.c @@ -183,10 +183,11 @@ update_var (session_env_t se, const char *string, size_t namelen, else if (!strncmp (se->array[idx]->name, string, namelen) && strlen (se->array[idx]->name) == namelen) { - /* Check if the value is the same; no need to update it, - except for updating the default flag. */ if (strlen (se->array[idx]->value) == valuelen) { + /* The new value has the same length. We can update it + in-place. */ + memcpy (se->array[idx]->value, value, valuelen); se->array[idx]->is_default = !!set_default; return 0; } ----------------------------------------------------------------------- Summary of changes: NEWS | 3 ++ common/ChangeLog | 5 +++ common/session-env.c | 5 ++- g10/call-agent.c | 3 -- g10/call-agent.h | 1 - g10/ecdh.c | 82 ++++++++++++++++++++----------------------------- g10/pkglue.c | 74 --------------------------------------------- g10/pkglue.h | 4 +- g10/pubkey-enc.c | 40 ++++++++++++++++++++++-- 9 files changed, 84 insertions(+), 133 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Thu Jan 13 06:40:23 2011 From: cvs at cvs.gnupg.org (by Andrey Jivsov) Date: Thu, 13 Jan 2011 06:40:23 +0100 Subject: [git] GCRYPT - branch, ECC-INTEGRATION-1-5, updated. libgcrypt-1.4.4-52-g9476066 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, ECC-INTEGRATION-1-5 has been updated via 94760660ab77bab25b24d67f8e813f1b49d35e07 (commit) from 899386826c85f1e757e75bcc5d5b2159d05676a0 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 94760660ab77bab25b24d67f8e813f1b49d35e07 Author: Andrey Jivsov Date: Wed Jan 12 21:20:57 2011 -0800 Fixed a typo, added logging. diff --git a/cipher/ecc.c b/cipher/ecc.c index f33cc1c..a7a5554 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -734,6 +734,11 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s) mpi_point_t I; mpi_ec_t ctx; + if (DBG_CIPHER) + { + log_mpidump ("ecdsa sign hash ", input ); + } + k = NULL; dr = mpi_alloc (0); sum = mpi_alloc (0); @@ -772,6 +777,12 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s) mpi_mulm (s, k_1, sum, skey->E.n); /* s = k^(-1)*(hash+(d*r)) mod n */ } + if (DBG_CIPHER) + { + log_mpidump ("ecdsa return r ", r ); + log_mpidump ("ecdsa return s ", s ); + } + leave: _gcry_mpi_ec_free (ctx); point_free (&I); @@ -859,7 +870,7 @@ verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s) log_mpidump (" y", y); log_mpidump (" r", r); log_mpidump (" s", s); - log_debug ("ecc verify: Not verified\n"); + log_debug ("ecc verify: Not verified (x != y)\n"); } err = GPG_ERR_BAD_SIGNATURE; goto leave; @@ -1374,7 +1385,6 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey ECC_secret_key sk; mpi_ec_t ctx; gcry_mpi_t result[2]; - mpi_point_t eph_Q; int err; (void)algo; @@ -1483,7 +1493,7 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, gcry_mpi_t *ske *result = NULL; if (DBG_CIPHER) - log_debug ("Called ecc_encrypt_raw data size=%d bits, flags=%08x\n", gcry_mpi_get_nbits (data), flags); + log_debug ("Called ecc_encrypt_raw data size=%d bits, flags=%08x\n", gcry_mpi_get_nbits (data[0]), flags); if ( !data || !data[0] || !skey[0] || !skey[1] || !skey[3] ) return GPG_ERR_BAD_MPI; ----------------------------------------------------------------------- Summary of changes: cipher/ecc.c | 16 +++++++++++++--- 1 files changed, 13 insertions(+), 3 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Thu Jan 13 06:41:10 2011 From: cvs at cvs.gnupg.org (by Andrey Jivsov) Date: Thu, 13 Jan 2011 06:41:10 +0100 Subject: [git] GnuPG - branch, ECC-INTEGRATION-2-1, updated. gnupg-2.1.0beta1-36-gb73d8ed Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, ECC-INTEGRATION-2-1 has been updated via b73d8ed06ffef8d2fd70ab2e48da9ef515472fe9 (commit) from 5761a9ba74e41f52660e20a1de700fe784c97832 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit b73d8ed06ffef8d2fd70ab2e48da9ef515472fe9 Author: Andrey Jivsov Date: Wed Jan 12 21:14:45 2011 -0800 Fixed key generation with P-521. Confirmed that signature generation and verification work. diff --git a/agent/agent.h b/agent/agent.h index 7716bb0..e31b6a7 100644 --- a/agent/agent.h +++ b/agent/agent.h @@ -215,6 +215,7 @@ const char *get_agent_ssh_socket_name (void); void *get_agent_scd_notify_event (void); #endif void agent_sighup_action (void); +int map_pk_openpgp_to_gcry (int openpgp_algo); /*-- command.c --*/ gpg_error_t agent_inq_pinentry_launched (ctrl_t ctrl, unsigned long pid); diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c index 3dba79e..73c31f7 100644 --- a/agent/cvt-openpgp.c +++ b/agent/cvt-openpgp.c @@ -27,7 +27,6 @@ #include "agent.h" #include "i18n.h" #include "cvt-openpgp.h" -#include "../include/cipher.h" /* for PUBKEY_ALGO_ECDSA, PUBKEY_ALGO_ECDH */ /* Helper to pass data via the callback to do_unprotect. */ @@ -50,12 +49,7 @@ struct try_do_unprotect_arg_s gcry_sexp_t *r_key; }; -/* TODO: it is also in misc, which is not linked with the agent */ -static int -map_pk_openpgp_to_gcry (int algo) -{ - return (algo==PUBKEY_ALGO_ECDSA ? GCRY_PK_ECDSA : (algo==PUBKEY_ALGO_ECDH ? GCRY_PK_ECDH : algo)); -} + /* Compute the keygrip from the public key and store it at GRIP. */ static gpg_error_t diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index ca150b4..d85283a 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -51,6 +51,7 @@ #include "gc-opt-flags.h" #include "exechelp.h" #include "asshelp.h" +#include "../include/cipher.h" /* for PUBKEY_ALGO_ECDSA, PUBKEY_ALGO_ECDH */ enum cmd_and_opt_values { aNull = 0, @@ -2301,3 +2302,10 @@ check_for_running_agent (int silent, int mode) assuan_release (ctx); return 0; } + +/* TODO: it is also in misc, which is not linked with the agent */ +int +map_pk_openpgp_to_gcry (int algo) +{ + return (algo==PUBKEY_ALGO_ECDSA ? GCRY_PK_ECDSA : (algo==PUBKEY_ALGO_ECDH ? GCRY_PK_ECDH : algo)); +} diff --git a/agent/pksign.c b/agent/pksign.c index ac5f4e1..a6dbf25 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -119,12 +119,15 @@ do_encode_dsa (const byte * md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey, gpg_error_t err; gcry_sexp_t hash; unsigned int qbits; + int gcry_pkalgo; *r_hash = NULL; - if (dsaalgo == GCRY_PK_ECDSA) + gcry_pkalgo = map_pk_openpgp_to_gcry( dsaalgo ); + + if (gcry_pkalgo == GCRY_PK_ECDSA) qbits = gcry_pk_get_nbits (pkey); - else if (dsaalgo == GCRY_PK_DSA) + else if (gcry_pkalgo == GCRY_PK_DSA) qbits = get_dsa_qbits (pkey); else return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO); @@ -143,20 +146,25 @@ do_encode_dsa (const byte * md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey, if (qbits < 160) { log_error (_("%s key uses an unsafe (%u bit) hash\n"), - gcry_pk_algo_name (dsaalgo), qbits); + gcry_pk_algo_name (gcry_pkalgo), qbits); return gpg_error (GPG_ERR_INV_LENGTH); } /* Check if we're too short. Too long is safe as we'll automatically left-truncate. */ - if (mdlen < qbits/8) + + /* This check would require the use of SHA512 with ECDSA 512. I think this is overkill to fail in this case. + * Therefore, relax the check, but only for ECDSA keys. We may need to adjust it later for general case. + * ( Note that the check is really a bug for ECDSA 521 as the only hash that matches it is SHA 512, but 512 < 521 ). + */ + if( mdlen < ((gcry_pkalgo==GCRY_PK_ECDSA && qbits>521) ? 512 : qbits) ) { log_error (_("a %zu bit hash is not valid for a %u bit %s key\n"), - mdlen*8, + mdlen, gcry_pk_get_nbits (pkey), - gcry_pk_algo_name (dsaalgo)); + gcry_pk_algo_name (gcry_pkalgo)); /* FIXME: we need to check the requirements for ECDSA. */ - if (mdlen < 20 || dsaalgo == GCRY_PK_DSA) + if (mdlen < 20 || gcry_pkalgo == GCRY_PK_DSA) return gpg_error (GPG_ERR_INV_LENGTH); } diff --git a/g10/seskey.c b/g10/seskey.c index 4cc9158..e50cf5c 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -288,7 +288,6 @@ encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo) * Therefore, relax the check, but only for ECDSA keys. We may need to adjust it later for general case. * ( Note that the check will never pass for ECDSA 521 anyway as the only hash that intended to match it is SHA 512, but 512 < 521 ). */ - //if (gcry_md_get_algo_dlen (hash_algo) < qbytes ) if (gcry_md_get_algo_dlen (hash_algo) < ((gcry_pkalgo==GCRY_PK_ECDSA && qbytes>(521)/8) ? 512/8 : qbytes) ) { log_error (_("%s key %s requires a %zu bit or larger hash, used hash-algo=%d\n"), @@ -297,8 +296,9 @@ encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo) return NULL; } + /* Note that in case of ECDSA 521 hash is always smaller than the key size */ if (gcry_mpi_scan (&frame, GCRYMPI_FMT_USG, - gcry_md_read (md, hash_algo), qbytes, &qbytes)) + gcry_md_read (md, hash_algo), gcry_md_get_algo_dlen (hash_algo), &qbytes)) BUG(); } else ----------------------------------------------------------------------- Summary of changes: agent/agent.h | 1 + agent/cvt-openpgp.c | 8 +------- agent/gpg-agent.c | 8 ++++++++ agent/pksign.c | 22 +++++++++++++++------- g10/seskey.c | 4 ++-- 5 files changed, 27 insertions(+), 16 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Thu Jan 13 15:54:12 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Thu, 13 Jan 2011 15:54:12 +0100 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta1-33-g52b9761 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, master has been updated via 52b9761c8847523d35de3484e4b7fdefbb0e6a4e (commit) via 8db3bf8c47a76e9f7d75863d49c172b5ddd94896 (commit) from 2732f2ff3f44a5aae969d5ce16a4de74478576a2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 52b9761c8847523d35de3484e4b7fdefbb0e6a4e Author: Werner Koch Date: Thu Jan 13 15:32:11 2011 +0100 ifset parts which are not in GnuPG 2.0 diff --git a/doc/debugging.texi b/doc/debugging.texi index 7b1d068..c83ab1e 100644 --- a/doc/debugging.texi +++ b/doc/debugging.texi @@ -103,7 +103,7 @@ used. Using the keyserver debug option as in is thus often helpful. Note that the actual output depends on the backend and may change from release to release. - + at ifset gpgtwoone @item Logging on WindowsCE For development, the best logging method on WindowsCE is the use of @@ -113,7 +113,7 @@ on the given port. (@pxref{option watchgnupg --tcp}). For in the field tests it is better to make use of the logging facility provided by the @command{gpgcedev} driver (part of libassuan); this is enabled by using a log file name of @file{GPG2:}. (@pxref{option --log-file}). - + at end ifset @end itemize diff --git a/doc/gnupg.texi b/doc/gnupg.texi index 86e192e..7bb54af 100644 --- a/doc/gnupg.texi +++ b/doc/gnupg.texi @@ -34,7 +34,7 @@ Published by the Free Software Foundation@* Boston, MA 02110-1301 USA @end iftex -Copyright @copyright{} 2002, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +Copyright @copyright{} 2002, 2004, 2005, 2006, 2007, 2010 Free Software Foundation, Inc. @quotation Permission is granted to copy, distribute and/or modify this document @@ -51,8 +51,10 @@ section entitled ``Copying''. * gpg2: (gnupg). OpenPGP encryption and signing tool. * gpgsm: (gnupg). S/MIME encryption and signing tool. * gpg-agent: (gnupg). The secret key daemon. + at ifset gpgtwoone * dirmngr: (gnupg). X.509 CRL and OCSP server. * dirmngr-client: (gnupg). X.509 CRL and OCSP client. + at end ifset @end direntry @@ -124,7 +126,9 @@ the administration and the architecture. * Installation:: A short installation guide. * Invoking GPG-AGENT:: How to launch the secret key daemon. + at ifset gpgtwoone * Invoking DIRMNGR:: How to launch the CRL and OCSP daemon. + at end ifset * Invoking GPG:: Using the OpenPGP protocol. * Invoking GPGSM:: Using the S/MIME protocol. * Invoking SCDAEMON:: How to handle Smartcards. @@ -156,7 +160,9 @@ the administration and the architecture. @include instguide.texi @include gpg-agent.texi + at ifset gpgtwoone @include dirmngr.texi + at end ifset @include gpg.texi @include gpgsm.texi @include scdaemon.texi diff --git a/doc/tools.texi b/doc/tools.texi index a21f413..c85f9e2 100644 --- a/doc/tools.texi +++ b/doc/tools.texi @@ -16,7 +16,9 @@ GnuPG comes with a couple of smaller tools: * gpgsm-gencert.sh:: Generate an X.509 certificate request. * gpg-preset-passphrase:: Put a passphrase into the cache. * gpg-connect-agent:: Communicate with a running agent. + at ifset gpgtwoone * dirmngr-client:: How to use the Dirmngr client tool. + at end ifset * gpgparsemail:: Parse a mail message into an annotated format * symcryptrun:: Call a simple symmetric encryption tool. * gpg-zip:: Encrypt or sign files into an archive. @@ -1434,6 +1436,7 @@ Print a list of available control commands. @include see-also-note.texi @end ifset + at ifset gpgtwoone @c @c DIRMNGR-CLIENT @c @@ -1594,7 +1597,7 @@ Squid's @option{external_acl_type} option. @command{gpgsm}(1) @include see-also-note.texi @end ifset - + at end ifset @c @c GPGPARSEMAIL commit 8db3bf8c47a76e9f7d75863d49c172b5ddd94896 Author: Werner Koch Date: Mon Jan 10 14:38:32 2011 +0100 Add ignore file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..699581b --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +Makefile.in +aclocal.m4 +autom4te.cache/ +configure +config.h.in +config.h +common/audit-events.h +common/status-codes.h +doc/gnupg.info* +doc/stamp-vti +doc/version.texi +po/gnupg2.pot ----------------------------------------------------------------------- Summary of changes: .gitignore | 12 ++++++++++++ doc/debugging.texi | 4 ++-- doc/gnupg.texi | 8 +++++++- doc/tools.texi | 5 ++++- 4 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 .gitignore hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Thu Jan 13 17:51:46 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Thu, 13 Jan 2011 17:51:46 +0100 Subject: [git] GnuPG - tag, gnupg-2.0.17, created. gnupg-2.0.16-29-g1f874f8 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The tag, gnupg-2.0.17 has been created at 1f874f860ce329aa90f2e6700874a44914b4fe34 (commit) - Log ----------------------------------------------------------------- commit 1f874f860ce329aa90f2e6700874a44914b4fe34 Author: Werner Koch Date: Thu Jan 13 16:01:21 2011 +0100 Finished preparations for 2.0.17 ----------------------------------------------------------------------- hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Sat Jan 15 04:02:07 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Sat, 15 Jan 2011 04:02:07 +0100 Subject: [git] GnuPG - branch, ECC-INTEGRATION-2-1, updated. gnupg-2.1.0beta1-37-ga66772a Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, ECC-INTEGRATION-2-1 has been updated via a66772aa6309a0e632ff802fd6dcfb034b61c5cf (commit) from b73d8ed06ffef8d2fd70ab2e48da9ef515472fe9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit a66772aa6309a0e632ff802fd6dcfb034b61c5cf Author: Werner Koch Date: Mon Jan 10 14:38:32 2011 +0100 Add ignore file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..699581b --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +Makefile.in +aclocal.m4 +autom4te.cache/ +configure +config.h.in +config.h +common/audit-events.h +common/status-codes.h +doc/gnupg.info* +doc/stamp-vti +doc/version.texi +po/gnupg2.pot ----------------------------------------------------------------------- Summary of changes: .gitignore | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-) create mode 100644 .gitignore hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Tue Jan 18 09:10:42 2011 From: cvs at cvs.gnupg.org (by Andreas Holzammer) Date: Tue, 18 Jan 2011 09:10:42 +0100 Subject: [git] Wincetools - branch, kdepimcetools, updated. 78287e3f2742c170d89ddcb448cbe14506e7c0dd Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "UNNAMED PROJECT". The branch, kdepimcetools has been updated via 78287e3f2742c170d89ddcb448cbe14506e7c0dd (commit) from d84cefe449bad56464449b8ac23cb03d2eace6e2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 78287e3f2742c170d89ddcb448cbe14506e7c0dd Author: Andreas Holzammer Date: Tue Jan 18 08:51:34 2011 +0100 Fix drawing bug diff --git a/loader/splashscreen/splashscreenstatic.bmp b/loader/splashscreen/splashscreenstatic.bmp index ddb4650..72f9cad 100644 Binary files a/loader/splashscreen/splashscreenstatic.bmp and b/loader/splashscreen/splashscreenstatic.bmp differ ----------------------------------------------------------------------- Summary of changes: loader/splashscreen/splashscreenstatic.bmp | Bin 768070 -> 768056 bytes 1 files changed, 0 insertions(+), 0 deletions(-) hooks/post-receive -- UNNAMED PROJECT http://git.gnupg.org From cvs at cvs.gnupg.org Wed Jan 19 16:50:33 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 19 Jan 2011 16:50:33 +0100 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta1-35-gaf500f0 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, master has been updated via af500f0ae490bc4262419fa52bac62677e1672fa (commit) via dcd20e18a5b581d93e8259722d5f1b69d3af992b (commit) from 52b9761c8847523d35de3484e4b7fdefbb0e6a4e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit af500f0ae490bc4262419fa52bac62677e1672fa Author: Werner Koch Date: Wed Jan 19 16:29:30 2011 +0100 Use estream for dirmngr's --gpgconf-list. Change insalled name of gpg2 for Wince. diff --git a/ChangeLog b/ChangeLog index 656fe72..d36c23c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2011-01-19 Werner Koch + + * configure.ac: Add new option --enable-gpg2-is-gpg. + (NAME_OF_INSTALLED_GPG): New ac_define. + * autogen.sh [--build-w32ce]: Use --enable-gpg2-is-gpg. + 2011-01-03 Werner Koch * README.SVN: Rename to README.GIT. @@ -16,7 +22,7 @@ 2010-11-17 Werner Koch - * configure.ac (ENABLE_CARD_SUPPORT): Define. + * configure.ac (ENABLE_CARD_SUPPORT): Define. 2010-10-27 Werner Koch diff --git a/autogen.sh b/autogen.sh index 72e5fee..d054155 100755 --- a/autogen.sh +++ b/autogen.sh @@ -104,7 +104,8 @@ if [ "$myhost" = "w32" ]; then [ -z "$w32root" ] && w32root="$HOME/w32ce_root" toolprefixes="$w32ce_toolprefixes arm-mingw32ce" extraoptions="--enable-dirmngr-auto-start --disable-scdaemon " - extraoptions="$extraoptions --disable-zip $w32ce_extraoptions" + extraoptions="$extraoptions --disable-zip --enable-gpg2-is-gpg" + extraoptions="$extraoptions $w32ce_extraoptions" ;; *) [ -z "$w32root" ] && w32root="$HOME/w32root" diff --git a/common/ChangeLog b/common/ChangeLog index fe9eb4f..3f38be1 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,6 +1,11 @@ +2011-01-19 Werner Koch + + * homedir.c (gnupg_module_name): Use NAME_OF_INSTALLED_GPG instead + of "gpg2". + 2011-01-18 Werner Koch - * estream.c (es_func_mem_write): FIX computation of NEWSIZE. + * estream.c (es_func_mem_write): Fix computation of NEWSIZE. 2011-01-10 Werner Koch diff --git a/common/homedir.c b/common/homedir.c index a6364f8..3d31bd3 100644 --- a/common/homedir.c +++ b/common/homedir.c @@ -528,7 +528,7 @@ gnupg_module_name (int which) X(bindir, "gpgsm"); case GNUPG_MODULE_NAME_GPG: - X(bindir, "gpg2"); + X(bindir, NAME_OF_INSTALLED_GPG); case GNUPG_MODULE_NAME_CONNECT_AGENT: X(bindir, "gpg-connect-agent"); diff --git a/configure.ac b/configure.ac index b6ed4b3..82d1509 100644 --- a/configure.ac +++ b/configure.ac @@ -168,6 +168,24 @@ show_gnupg_dirmngr_ldap_pgm="(default)" test -n "$GNUPG_DIRMNGR_LDAP_PGM" \ && show_gnupg_dirmngr_ldap_pgm="$GNUPG_DIRMNGR_LDAP_PGM" +# +# On some platforms gpg2 is usually installed as gpg without using a +# symlink. For correct operation of gpgconf it needs to know the +# installed name of gpg. This option sets "gpg2"'s installed name to +# just "gpg". Note that it might be required to rename gpg2 to gpg +# manually after the build process. +# +AC_ARG_ENABLE(gpg2-is-gpg, + AC_HELP_STRING([--enable-gpg2-is-gpg],[Set installed name of gpg2 to gpg]), + gpg2_is_gpg=$enableval) +if test "$gpg2_is_gpg" = "yes"; then + name_of_installed_gpg=gpg +else + name_of_installed_gpg=gpg2 +fi +AC_DEFINE_UNQUOTED(NAME_OF_INSTALLED_GPG, "$name_of_installed_gpg", + [The name of the installed GPG tool]) + # Some folks want to use only the agent from this packet. Make it # easier for them by providing the configure option diff --git a/dirmngr/ChangeLog b/dirmngr/ChangeLog index 2c20875..9711846 100644 --- a/dirmngr/ChangeLog +++ b/dirmngr/ChangeLog @@ -1,3 +1,7 @@ +2011-01-19 Werner Koch + + * dirmngr.c (main): Use es_printf for --gpgconf-list. + 2010-12-14 Werner Koch * cdb.h (struct cdb) [W32]: Add field CDB_MAPPING. diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c index 9b06851..ae922fa 100644 --- a/dirmngr/dirmngr.c +++ b/dirmngr/dirmngr.c @@ -1019,7 +1019,7 @@ main (int argc, char **argv) start of the dirmngr. */ #ifdef HAVE_W32_SYSTEM pid = getpid (); - printf ("set DIRMNGR_INFO=%s;%lu;1\n", socket_name, (ulong) pid); + es_printf ("set DIRMNGR_INFO=%s;%lu;1\n", socket_name, (ulong) pid); #else pid = pth_fork (); if (pid == (pid_t)-1) @@ -1051,11 +1051,11 @@ main (int argc, char **argv) if (csh_style) { *strchr (infostr, '=') = ' '; - printf ( "setenv %s\n", infostr); + es_printf ( "setenv %s\n", infostr); } else { - printf ( "%s; export DIRMNGR_INFO;\n", infostr); + es_printf ( "%s; export DIRMNGR_INFO;\n", infostr); } free (infostr); exit (0); @@ -1220,15 +1220,15 @@ main (int argc, char **argv) "dirmngr.conf", NULL ); filename = percent_escape (opt.config_filename, NULL); - printf ("gpgconf-dirmngr.conf:%lu:\"%s\n", + es_printf ("gpgconf-dirmngr.conf:%lu:\"%s\n", GC_OPT_FLAG_DEFAULT, filename); xfree (filename); - printf ("verbose:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("quiet:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("debug-level:%lu:\"none\n", flags | GC_OPT_FLAG_DEFAULT); - printf ("log-file:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("force:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("verbose:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("quiet:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("debug-level:%lu:\"none\n", flags | GC_OPT_FLAG_DEFAULT); + es_printf ("log-file:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("force:%lu:\n", flags | GC_OPT_FLAG_NONE); /* --csh and --sh are mutually exclusive, something we can not express in GPG Conf. --options is only usable from the @@ -1241,34 +1241,34 @@ main (int argc, char **argv) "ldapservers.conf":"dirmngr_ldapservers.conf", NULL); filename_esc = percent_escape (filename, NULL); - printf ("ldapserverlist-file:%lu:\"%s\n", flags | GC_OPT_FLAG_DEFAULT, + es_printf ("ldapserverlist-file:%lu:\"%s\n", flags | GC_OPT_FLAG_DEFAULT, filename_esc); xfree (filename_esc); xfree (filename); - printf ("ldaptimeout:%lu:%u\n", + es_printf ("ldaptimeout:%lu:%u\n", flags | GC_OPT_FLAG_DEFAULT, DEFAULT_LDAP_TIMEOUT); - printf ("max-replies:%lu:%u\n", + es_printf ("max-replies:%lu:%u\n", flags | GC_OPT_FLAG_DEFAULT, DEFAULT_MAX_REPLIES); - printf ("allow-ocsp:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("ocsp-responder:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("ocsp-signer:%lu:\n", flags | GC_OPT_FLAG_NONE); - - printf ("faked-system-time:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("no-greeting:%lu:\n", flags | GC_OPT_FLAG_NONE); - - printf ("disable-http:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("disable-ldap:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("honor-http-proxy:%lu\n", flags | GC_OPT_FLAG_NONE); - printf ("http-proxy:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("ldap-proxy:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("only-ldap-proxy:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("ignore-ldap-dp:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("ignore-http-dp:%lu:\n", flags | GC_OPT_FLAG_NONE); - printf ("ignore-ocsp-service-url:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("allow-ocsp:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("ocsp-responder:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("ocsp-signer:%lu:\n", flags | GC_OPT_FLAG_NONE); + + es_printf ("faked-system-time:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("no-greeting:%lu:\n", flags | GC_OPT_FLAG_NONE); + + es_printf ("disable-http:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("disable-ldap:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("honor-http-proxy:%lu\n", flags | GC_OPT_FLAG_NONE); + es_printf ("http-proxy:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("ldap-proxy:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("only-ldap-proxy:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("ignore-ldap-dp:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("ignore-http-dp:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("ignore-ocsp-service-url:%lu:\n", flags | GC_OPT_FLAG_NONE); /* Note: The next one is to fix a typo in gpgconf - should be removed eventually. */ - printf ("ignore-ocsp-servic-url:%lu:\n", flags | GC_OPT_FLAG_NONE); + es_printf ("ignore-ocsp-servic-url:%lu:\n", flags | GC_OPT_FLAG_NONE); } cleanup (); return !!rc; commit dcd20e18a5b581d93e8259722d5f1b69d3af992b Author: Werner Koch Date: Tue Jan 18 12:26:05 2011 +0100 Fix computation of NEWSIZE in es_func_mem_write. The function used to fail and return EINVAL when enlarging the buffer. diff --git a/common/ChangeLog b/common/ChangeLog index 6a6f6e0..fe9eb4f 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,3 +1,7 @@ +2011-01-18 Werner Koch + + * estream.c (es_func_mem_write): FIX computation of NEWSIZE. + 2011-01-10 Werner Koch * session-env.c (update_var): Fix same value detection. Fixes diff --git a/common/estream.c b/common/estream.c index bc25452..416aa83 100644 --- a/common/estream.c +++ b/common/estream.c @@ -641,7 +641,7 @@ es_func_mem_write (void *cookie, const void *buffer, size_t size) if (!mem_cookie->memory_size) newsize = size; /* Not yet allocated. */ else - newsize = mem_cookie->memory_size + (nleft - size); + newsize = mem_cookie->memory_size + (size - nleft); if (newsize < mem_cookie->offset) { _set_errno (EINVAL); ----------------------------------------------------------------------- Summary of changes: ChangeLog | 8 ++++++- autogen.sh | 3 +- common/ChangeLog | 9 ++++++++ common/estream.c | 2 +- common/homedir.c | 2 +- configure.ac | 18 ++++++++++++++++ dirmngr/ChangeLog | 4 +++ dirmngr/dirmngr.c | 58 ++++++++++++++++++++++++++-------------------------- 8 files changed, 71 insertions(+), 33 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Wed Jan 19 18:24:51 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 19 Jan 2011 18:24:51 +0100 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta1-36-g13acd78 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, master has been updated via 13acd78a39750e3990684a5bb0951fe0db83fc5a (commit) from af500f0ae490bc4262419fa52bac62677e1672fa (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 13acd78a39750e3990684a5bb0951fe0db83fc5a Author: Werner Koch Date: Wed Jan 19 18:05:15 2011 +0100 Fixed a CR/LF problem on Windows diff --git a/agent/ChangeLog b/agent/ChangeLog index ce1fdcc..542695b 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2011-01-19 Werner Koch + + * trustlist.c (read_one_trustfile): Also chop an CR. + 2010-12-02 Werner Koch * gpg-agent.c (CHECK_OWN_SOCKET_INTERVAL) [W32CE]: Set to 60 diff --git a/agent/trustlist.c b/agent/trustlist.c index 791df96..d565982 100644 --- a/agent/trustlist.c +++ b/agent/trustlist.c @@ -139,8 +139,9 @@ read_one_trustfile (const char *fname, int allow_include, while (es_fgets (line, DIM(line)-1, fp)) { lnr++; - - if (!*line || line[strlen(line)-1] != '\n') + + n = strlen (line); + if (!n || line[n-1] != '\n') { /* Eat until end of line. */ while ( (c=es_getc (fp)) != EOF && c != '\n') @@ -151,7 +152,9 @@ read_one_trustfile (const char *fname, int allow_include, fname, lnr, gpg_strerror (err)); continue; } - line[strlen(line)-1] = 0; /* Chop the LF. */ + line[--n] = 0; /* Chop the LF. */ + if (n && line[n-1] == '\r') + line[--n] = 0; /* Chop an optional CR. */ /* Allow for empty lines and spaces */ for (p=line; spacep (p); p++) ----------------------------------------------------------------------- Summary of changes: agent/ChangeLog | 4 ++++ agent/trustlist.c | 9 ++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Thu Jan 20 15:45:39 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Thu, 20 Jan 2011 15:45:39 +0100 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta1-45-g62842cc Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, master has been updated via 62842cc7fe614e278638c008d0192d68a05a555a (commit) via 2b933ae8f6324115e1ede81996ab18fe2ac90715 (commit) from 49d25d3185636237b356781cdde7960f234f2d11 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 62842cc7fe614e278638c008d0192d68a05a555a Author: Werner Koch Date: Thu Jan 20 15:25:47 2011 +0100 Remove keyserver/ from the build system. diff --git a/ChangeLog b/ChangeLog index d36c23c..11b37eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2011-01-20 Werner Koch + + * configure.ac (AC_CONFIG_FILES): Remove keyserver/. + 2011-01-19 Werner Koch * configure.ac: Add new option --enable-gpg2-is-gpg. diff --git a/configure.ac b/configure.ac index 82d1509..b108d19 100644 --- a/configure.ac +++ b/configure.ac @@ -1683,9 +1683,6 @@ agent/Makefile scd/Makefile g13/Makefile dirmngr/Makefile -keyserver/Makefile -keyserver/gpg2keys_mailto -keyserver/gpg2keys_test tools/gpg-zip tools/Makefile doc/Makefile @@ -1693,6 +1690,11 @@ tests/Makefile tests/openpgp/Makefile tests/pkits/Makefile ]) +#keyserver/Makefile +#keyserver/gpg2keys_mailto +#keyserver/gpg2keys_test + + AC_OUTPUT diff --git a/po/de.po b/po/de.po index 59da727..3f4a978 100644 --- a/po/de.po +++ b/po/de.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: gnupg-2.1.0\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2011-01-20 14:32+0100\n" +"POT-Creation-Date: 2011-01-20 15:15+0100\n" "PO-Revision-Date: 2011-01-20 15:10+0100\n" "Last-Translator: Werner Koch \n" "Language-Team: German \n" @@ -894,12 +894,12 @@ msgstr "Fehler bei Ausf?hrung von `%s': beendet\n" msgid "error getting exit code of process %d: %s\n" msgstr "Fehler beim Holen des Exitwerte des Prozesses %d: %s\n" -#: common/http.c:1597 +#: common/http.c:1607 #, c-format msgid "error creating socket: %s\n" msgstr "Fehler beim Erstellen des Sockets: %s\n" -#: common/http.c:1641 +#: common/http.c:1651 msgid "host not found" msgstr "Host nicht gefunden" commit 2b933ae8f6324115e1ede81996ab18fe2ac90715 Author: Werner Koch Date: Thu Jan 20 15:11:25 2011 +0100 Fix for bug#1313. de.po update. diff --git a/NEWS b/NEWS index 2153733..5f9fd0a 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,9 @@ Noteworthy changes in version 2.1.0beta2 (unreleased) * Fixed TTY management for pinentries and session variable update problem. + * Dirmngr has taken over the function of the keyserver helpers. Thus + we now have a specified direct interface to keyservers via Dirmngr. + Noteworthy changes in version 2.1.0beta1 (2010-10-26) ----------------------------------------------------- diff --git a/common/ChangeLog b/common/ChangeLog index 88e91f9..0150658 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,5 +1,16 @@ 2011-01-20 Werner Koch + Fix bug#1313. + + * http.c (my_select): New. Define to pth_select if building with Pth. + (start_server, write_server, cookie_read, cookie_write): Use it. + (my_connect): New. Define to pth_connect if building with Pth. + (connect_server): Use it. + (my_accept): New. Define to pth_accept if building with Pth. + (start_server): Use it. + +2011-01-20 Werner Koch + * util.h (struct b64state): Add field LASTERR. * b64enc.c (enc_start, b64enc_write, b64enc_finish): Handle LASTERR. This is to make sure that we don't leak strduped data. diff --git a/common/http.c b/common/http.c index 4d35361..b50b6b8 100644 --- a/common/http.c +++ b/common/http.c @@ -105,6 +105,16 @@ struct srventry #endif/*!USE_DNS_SRV*/ +#ifdef HAVE_PTH +# define my_select(a,b,c,d,e) pth_select ((a), (b), (c), (d), (e)) +# define my_connect(a,b,c) pth_connect ((a), (b), (c)) +# define my_accept(a,b,c) pth_accept ((a), (b), (c)) +#else +# define my_select(a,b,c,d,e) select ((a), (b), (c), (d), (e)) +# define my_connect(a,b,c) connect ((a), (b), (c)) +# define my_accept(a,b,c) accept ((a), (b), (c)) +#endif + #ifdef HAVE_W32_SYSTEM #define sock_close(a) closesocket(a) #else @@ -1421,14 +1431,14 @@ start_server () FD_ZERO (&rfds); FD_SET (fd, &rfds); - if (select (fd + 1, &rfds, NULL, NULL, NULL) <= 0) + if (my_select (fd + 1, &rfds, NULL, NULL, NULL) <= 0) continue; /* ignore any errors */ if (!FD_ISSET (fd, &rfds)) continue; addrlen = sizeof peer; - client = accept (fd, (struct sockaddr *) &peer, &addrlen); + client = my_accept (fd, (struct sockaddr *) &peer, &addrlen); if (client == -1) continue; /* oops */ @@ -1498,7 +1508,7 @@ connect_server (const char *server, unsigned short port, addr.sin_port = htons(port); memcpy (&addr.sin_addr,&inaddr,sizeof(inaddr)); - if (!connect (sock,(struct sockaddr *)&addr,sizeof(addr)) ) + if (!my_connect (sock,(struct sockaddr *)&addr,sizeof(addr)) ) return sock; sock_close(sock); return -1; @@ -1566,7 +1576,7 @@ connect_server (const char *server, unsigned short port, return -1; } - if (connect (sock, ai->ai_addr, ai->ai_addrlen)) + if (my_connect (sock, ai->ai_addr, ai->ai_addrlen)) last_errno = errno; else connected = 1; @@ -1620,7 +1630,7 @@ connect_server (const char *server, unsigned short port, for (i = 0; host->h_addr_list[i] && !connected; i++) { memcpy (&addr.sin_addr, host->h_addr_list[i], host->h_length); - if (connect (sock, (struct sockaddr *) &addr, sizeof (addr))) + if (my_connect (sock, (struct sockaddr *) &addr, sizeof (addr))) last_errno = errno; else { @@ -1660,7 +1670,6 @@ write_server (int sock, const char *data, size_t length) int nleft; int nwritten; - /* FIXME: We would better use pth I/O functions. */ nleft = length; while (nleft > 0) { @@ -1687,7 +1696,7 @@ write_server (int sock, const char *data, size_t length) tv.tv_sec = 0; tv.tv_usec = 50000; - select (0, NULL, NULL, NULL, &tv); + my_select (0, NULL, NULL, NULL, &tv); continue; } log_info ("network write failed: %s\n", strerror (errno)); @@ -1733,7 +1742,7 @@ cookie_read (void *cookie, void *buffer, size_t size) tv.tv_sec = 0; tv.tv_usec = 50000; - select (0, NULL, NULL, NULL, &tv); + my_select (0, NULL, NULL, NULL, &tv); goto again; } if (nread == GNUTLS_E_REHANDSHAKE) @@ -1795,7 +1804,7 @@ cookie_write (void *cookie, const void *buffer, size_t size) tv.tv_sec = 0; tv.tv_usec = 50000; - select (0, NULL, NULL, NULL, &tv); + my_select (0, NULL, NULL, NULL, &tv); continue; } log_info ("TLS network write failed: %s\n", diff --git a/po/ChangeLog b/po/ChangeLog index c0f6240..d8e9c42 100644 --- a/po/ChangeLog +++ b/po/ChangeLog @@ -1,3 +1,7 @@ +2011-01-20 Werner Koch + + * de.po: Fix two fuzzies. + 2010-10-21 Werner Koch * POTFILES.in: Add files in dirmngr/. diff --git a/po/de.po b/po/de.po index 8545431..59da727 100644 --- a/po/de.po +++ b/po/de.po @@ -9,8 +9,8 @@ msgid "" msgstr "" "Project-Id-Version: gnupg-2.1.0\n" "Report-Msgid-Bugs-To: translations at gnupg.org\n" -"POT-Creation-Date: 2011-01-14 21:03+0100\n" -"PO-Revision-Date: 2010-11-23 19:38+0100\n" +"POT-Creation-Date: 2011-01-20 14:32+0100\n" +"PO-Revision-Date: 2011-01-20 15:10+0100\n" "Last-Translator: Werner Koch \n" "Language-Team: German \n" "MIME-Version: 1.0\n" @@ -696,45 +696,45 @@ msgstr "Vom Benutzer abgebrochen\n" msgid "error while asking for the passphrase: %s\n" msgstr "Fehler bei der Abfrage der Passphrase: %s\n" -#: agent/trustlist.c:135 agent/trustlist.c:332 dirmngr/dirmngr.c:1374 +#: agent/trustlist.c:135 agent/trustlist.c:335 dirmngr/dirmngr.c:1374 #, c-format msgid "error opening `%s': %s\n" msgstr "Fehler beim ?ffnen von `%s': %s\n" -#: agent/trustlist.c:150 common/helpfile.c:63 common/helpfile.c:79 +#: agent/trustlist.c:151 common/helpfile.c:63 common/helpfile.c:79 #, c-format msgid "file `%s', line %d: %s\n" msgstr "Datei `%s', Zeile %d: %s\n" -#: agent/trustlist.c:170 agent/trustlist.c:178 +#: agent/trustlist.c:173 agent/trustlist.c:181 #, c-format msgid "statement \"%s\" ignored in `%s', line %d\n" msgstr "" "Anweisung \"%s\" in `%s', Zeile %d\n" " ignoriert\n" -#: agent/trustlist.c:184 +#: agent/trustlist.c:187 #, c-format msgid "system trustlist `%s' not available\n" msgstr "" "Systemliste der vertrauensw?rdigen Zertifikate '%s' ist nicht vorhanden\n" -#: agent/trustlist.c:228 +#: agent/trustlist.c:231 #, c-format msgid "bad fingerprint in `%s', line %d\n" msgstr "fehlerhafter Fingerabdruck in `%s', Zeile %d\n" -#: agent/trustlist.c:253 agent/trustlist.c:260 +#: agent/trustlist.c:256 agent/trustlist.c:263 #, c-format msgid "invalid keyflag in `%s', line %d\n" msgstr "Ung?ltiges Schl?sselflag in `%s', Zeile %d\n" -#: agent/trustlist.c:294 common/helpfile.c:126 +#: agent/trustlist.c:297 common/helpfile.c:126 #, c-format msgid "error reading `%s', line %d: %s\n" msgstr "Fehler beim Lesen von `%s', Zeile %d: %s\n" -#: agent/trustlist.c:398 agent/trustlist.c:448 +#: agent/trustlist.c:401 agent/trustlist.c:451 msgid "error reading list of trusted root certificates\n" msgstr "Fehler beim Lesen der Liste vertrauensw?rdiger root-Zertifikate\n" @@ -746,7 +746,7 @@ msgstr "Fehler beim Lesen der Liste vertrauensw?rdiger root-Zertifikate\n" #. plain % sign, you need to encode it as "%%25". The #. "%s" gets replaced by the name as stored in the #. certificate. -#: agent/trustlist.c:609 +#: agent/trustlist.c:612 #, c-format msgid "" "Do you ultimately trust%%0A \"%s\"%%0Ato correctly certify user " @@ -755,11 +755,11 @@ msgstr "" "Wenn Sie vollst?ndiges Vertrauen haben, da?%%0A \"%s\"%%" "0ABenutzerzertifikate verl??lich zertifiziert, so antworten Sie mit \"Ja\"." -#: agent/trustlist.c:618 common/audit.c:467 +#: agent/trustlist.c:621 common/audit.c:467 msgid "Yes" msgstr "Ja" -#: agent/trustlist.c:618 common/audit.c:469 +#: agent/trustlist.c:621 common/audit.c:469 msgid "No" msgstr "Nein" @@ -771,7 +771,7 @@ msgstr "Nein" #. "%%25". The second "%s" gets replaced by a hexdecimal #. fingerprint string whereas the first one receives the name #. as stored in the certificate. -#: agent/trustlist.c:652 +#: agent/trustlist.c:655 #, c-format msgid "" "Please verify that the certificate identified as:%%0A \"%s\"%%0Ahas the " @@ -783,11 +783,11 @@ msgstr "" #. TRANSLATORS: "Correct" is the label of a button and intended #. to be hit if the fingerprint matches the one of the CA. The #. other button is "the default "Cancel" of the Pinentry. -#: agent/trustlist.c:666 +#: agent/trustlist.c:669 msgid "Correct" msgstr "Korrekt" -#: agent/trustlist.c:666 +#: agent/trustlist.c:669 msgid "Wrong" msgstr "Falsch" @@ -894,12 +894,12 @@ msgstr "Fehler bei Ausf?hrung von `%s': beendet\n" msgid "error getting exit code of process %d: %s\n" msgstr "Fehler beim Holen des Exitwerte des Prozesses %d: %s\n" -#: common/http.c:1568 +#: common/http.c:1597 #, c-format msgid "error creating socket: %s\n" msgstr "Fehler beim Erstellen des Sockets: %s\n" -#: common/http.c:1612 +#: common/http.c:1641 msgid "host not found" msgstr "Host nicht gefunden" @@ -1005,9 +1005,9 @@ msgid "no running gpg-agent - starting `%s'\n" msgstr "Kein aktiver gpg-agent - `%s' wird gestartet\n" #: common/asshelp.c:436 -#, fuzzy, c-format +#, c-format msgid "waiting for the agent to come up ... (%ds)\n" -msgstr "Warte %d Sekunden bis der gpg-agent bereit ist\n" +msgstr "Warte bis der gpg-agent bereit ist ... (%ds)\n" #: common/asshelp.c:445 common/asshelp.c:534 msgid "connection to agent established\n" @@ -1023,9 +1023,9 @@ msgid "no running Dirmngr - starting `%s'\n" msgstr "Kein aktiver Dirmngr - `%s' wird gestartet\n" #: common/asshelp.c:630 -#, fuzzy, c-format +#, c-format msgid "waiting for the dirmngr to come up ... (%ds)\n" -msgstr "Warte %d Sekunden bis der Dirmngr bereit ist\n" +msgstr "Warte bis der Dirmngr bereit ist ... (%ds)\n" #: common/asshelp.c:639 common/asshelp.c:668 msgid "connection to the dirmngr established\n" @@ -1552,7 +1552,7 @@ msgstr "Fehler: URL ist zu lang (Grenze betr?gt %d Zeichen).\n" msgid "error allocating enough memory: %s\n" msgstr "Fehler beim Zuteilen gen?genden Speichers: %s\n" -#: g10/card-util.c:814 g10/import.c:291 dirmngr/crlcache.c:649 +#: g10/card-util.c:814 g10/import.c:317 dirmngr/crlcache.c:649 #: dirmngr/crlcache.c:654 dirmngr/crlcache.c:908 dirmngr/crlcache.c:914 #: dirmngr/dirmngr.c:1412 #, c-format @@ -1817,13 +1817,13 @@ msgstr "--output funktioniert nicht bei diesem Befehl\n" msgid "can't open `%s'\n" msgstr "'%s' kann nicht ge?ffnet werden\n" -#: g10/delkey.c:73 g10/export.c:637 g10/keyedit.c:3355 g10/keyserver.c:1751 +#: g10/delkey.c:73 g10/export.c:691 g10/keyedit.c:3355 g10/keyserver.c:1134 #: g10/revoke.c:227 #, c-format msgid "key \"%s\" not found: %s\n" msgstr "Schl?ssel \"%s\" nicht gefunden: %s\n" -#: g10/delkey.c:81 g10/export.c:701 g10/getkey.c:2881 g10/keyserver.c:1765 +#: g10/delkey.c:81 g10/export.c:755 g10/getkey.c:2881 g10/keyserver.c:1148 #: g10/revoke.c:233 g10/revoke.c:479 #, c-format msgid "error reading keyblock: %s\n" @@ -2044,25 +2044,25 @@ msgstr "W?hrend des Exports soviel wie m?glich vom Schl?ssel entfernen" msgid "export keys in an S-expression based format" msgstr "Exportiere Schl?ssel in einem auf S-Ausdr?cken basierenden Format" -#: g10/export.c:652 +#: g10/export.c:706 msgid "exporting secret keys not allowed\n" msgstr "Exportieren geheimer Schl?ssel ist nicht erlaubt\n" -#: g10/export.c:725 +#: g10/export.c:779 #, c-format msgid "key %s: PGP 2.x style key - skipped\n" msgstr "Schl?ssel %s: PGP 2.x-artiger Schl?ssel - ?bersprungen\n" -#: g10/export.c:909 +#: g10/export.c:963 #, c-format msgid "key %s: key material on-card - skipped\n" msgstr "Schl?ssel %s: Schl?sselmaterial ist auf einer Karte - ?bersprungen\n" -#: g10/export.c:1008 +#: g10/export.c:1062 msgid " - skipped" msgstr " - ?bersprungen" -#: g10/export.c:1079 +#: g10/export.c:1133 msgid "WARNING: nothing exported\n" msgstr "WARNUNG: Nichts exportiert\n" @@ -2833,7 +2833,7 @@ msgstr "--edit-key User-ID [Befehle]" msgid "--passwd " msgstr "--passwd User-ID" -#: g10/gpg.c:3744 +#: g10/gpg.c:3744 g10/keyserver.c:1634 #, c-format msgid "keyserver send failed: %s\n" msgstr "Senden an Schl?sselserver fehlgeschlagen: %s\n" @@ -2950,92 +2950,92 @@ msgstr "entferne nach dem Import unbrauchbare Teile des Schl?ssels" msgid "remove as much as possible from key after import" msgstr "nach dem Import soviel wie m?glich aus dem Schl?ssel entfernen" -#: g10/import.c:277 +#: g10/import.c:303 #, c-format msgid "skipping block of type %d\n" msgstr "?berspringe den Block vom Typ %d\n" -#: g10/import.c:286 +#: g10/import.c:312 #, c-format msgid "%lu keys processed so far\n" msgstr "%lu Schl?ssel bislang bearbeitet\n" -#: g10/import.c:303 +#: g10/import.c:329 #, c-format msgid "Total number processed: %lu\n" msgstr "Anzahl insgesamt bearbeiteter Schl?ssel: %lu\n" -#: g10/import.c:305 +#: g10/import.c:331 #, c-format msgid " skipped new keys: %lu\n" msgstr " ignorierte neue Schl?ssel: %lu\n" -#: g10/import.c:308 +#: g10/import.c:334 #, c-format msgid " w/o user IDs: %lu\n" msgstr " ohne User-ID: %lu\n" -#: g10/import.c:310 sm/import.c:130 +#: g10/import.c:336 sm/import.c:130 #, c-format msgid " imported: %lu" msgstr " importiert: %lu" -#: g10/import.c:316 sm/import.c:134 +#: g10/import.c:342 sm/import.c:134 #, c-format msgid " unchanged: %lu\n" msgstr " unver?ndert: %lu\n" -#: g10/import.c:318 +#: g10/import.c:344 #, c-format msgid " new user IDs: %lu\n" msgstr " neue User-IDs: %lu\n" -#: g10/import.c:320 +#: g10/import.c:346 #, c-format msgid " new subkeys: %lu\n" msgstr " neue Unterschl?ssel: %lu\n" -#: g10/import.c:322 +#: g10/import.c:348 #, c-format msgid " new signatures: %lu\n" msgstr " neue Signaturen: %lu\n" -#: g10/import.c:324 +#: g10/import.c:350 #, c-format msgid " new key revocations: %lu\n" msgstr " neue Schl?sselwiderrufe: %lu\n" -#: g10/import.c:326 sm/import.c:136 +#: g10/import.c:352 sm/import.c:136 #, c-format msgid " secret keys read: %lu\n" msgstr " gelesene geheime Schl?ssel: %lu\n" -#: g10/import.c:328 sm/import.c:138 +#: g10/import.c:354 sm/import.c:138 #, c-format msgid " secret keys imported: %lu\n" msgstr " geheime Schl?ssel importiert: %lu\n" -#: g10/import.c:330 sm/import.c:140 +#: g10/import.c:356 sm/import.c:140 #, c-format msgid " secret keys unchanged: %lu\n" msgstr " unver?nderte geh. Schl.: %lu\n" -#: g10/import.c:332 sm/import.c:142 +#: g10/import.c:358 sm/import.c:142 #, c-format msgid " not imported: %lu\n" msgstr " nicht importiert: %lu\n" -#: g10/import.c:334 +#: g10/import.c:360 #, c-format msgid " signatures cleaned: %lu\n" msgstr " Signaturen bereinigt: %lu\n" -#: g10/import.c:336 +#: g10/import.c:362 #, c-format msgid " user IDs cleaned: %lu\n" msgstr " User-IDs bereinigt: %lu\n" -#: g10/import.c:614 +#: g10/import.c:640 #, c-format msgid "" "WARNING: key %s contains preferences for unavailable\n" @@ -3044,328 +3044,328 @@ msgstr "" "WARNUNG: Schl?ssel %s hat Einstellungen zu nicht verf?gbaren\n" "Verfahren f?r folgende User-ID:\n" -#: g10/import.c:655 +#: g10/import.c:681 #, c-format msgid " \"%s\": preference for cipher algorithm %s\n" msgstr " \"%s\": Einstellungen des Verschl?sselungsverfahren %s\n" -#: g10/import.c:670 +#: g10/import.c:696 #, c-format msgid " \"%s\": preference for digest algorithm %s\n" msgstr " \"%s\": Einstellungen der Hashmethode %s\n" -#: g10/import.c:682 +#: g10/import.c:708 #, c-format msgid " \"%s\": preference for compression algorithm %s\n" msgstr " \"%s\": Einstellungen der Komprimierungsverfahren %s\n" -#: g10/import.c:695 +#: g10/import.c:721 msgid "it is strongly suggested that you update your preferences and\n" msgstr "es ist extrem empfehlenswert Ihre Einstellungen zu ?ndern und\n" -#: g10/import.c:697 +#: g10/import.c:723 msgid "re-distribute this key to avoid potential algorithm mismatch problems\n" msgstr "" "diesen Schl?ssel wieder zu verteilen, um m?gliche Probleme durch unpassende " "Verfahrenskombinationen zu vermeiden\n" -#: g10/import.c:721 +#: g10/import.c:747 #, c-format msgid "you can update your preferences with: gpg --edit-key %s updpref save\n" msgstr "" "Sie k?nnen Ihren Einstellungen mittels \"gpg --edit-key %s updpref save\" " "?ndern\n" -#: g10/import.c:775 g10/import.c:1403 +#: g10/import.c:801 g10/import.c:1429 #, c-format msgid "key %s: no user ID\n" msgstr "Schl?ssel %s: Keine User-ID\n" -#: g10/import.c:804 +#: g10/import.c:830 #, c-format msgid "key %s: PKS subkey corruption repaired\n" msgstr "Schl?ssel %s: PKS Unterschl?sseldefekt repariert\n" -#: g10/import.c:819 +#: g10/import.c:845 #, c-format msgid "key %s: accepted non self-signed user ID \"%s\"\n" msgstr "Schl?ssel %s: Nicht eigenbeglaubigte User-ID `%s' ?bernommen\n" -#: g10/import.c:825 +#: g10/import.c:851 #, c-format msgid "key %s: no valid user IDs\n" msgstr "Schl?ssel %s: Keine g?ltigen User-IDs\n" -#: g10/import.c:827 +#: g10/import.c:853 msgid "this may be caused by a missing self-signature\n" msgstr "dies k?nnte durch fehlende Eigenbeglaubigung verursacht worden sein\n" -#: g10/import.c:837 g10/import.c:1523 +#: g10/import.c:863 g10/import.c:1549 #, c-format msgid "key %s: public key not found: %s\n" msgstr "Schl?ssel %s: ?ffentlicher Schl?ssel nicht gefunden: %s\n" -#: g10/import.c:843 +#: g10/import.c:869 #, c-format msgid "key %s: new key - skipped\n" msgstr "Schl?ssel %s: neuer Schl?ssel - ?bersprungen\n" -#: g10/import.c:852 +#: g10/import.c:878 #, c-format msgid "no writable keyring found: %s\n" msgstr "kein schreibbarer Schl?sselbund gefunden: %s\n" -#: g10/import.c:857 g10/openfile.c:202 g10/openfile.c:293 g10/sign.c:874 +#: g10/import.c:883 g10/openfile.c:202 g10/openfile.c:293 g10/sign.c:874 #: g10/sign.c:1185 #, c-format msgid "writing to `%s'\n" msgstr "Schreiben nach '%s'\n" -#: g10/import.c:861 g10/import.c:961 g10/import.c:1584 +#: g10/import.c:887 g10/import.c:987 g10/import.c:1610 #, c-format msgid "error writing keyring `%s': %s\n" msgstr "Fehler beim Schreiben des Schl?sselbundes `%s': %s\n" -#: g10/import.c:880 +#: g10/import.c:906 #, c-format msgid "key %s: public key \"%s\" imported\n" msgstr "Schl?ssel %s: ?ffentlicher Schl?ssel \"%s\" importiert\n" -#: g10/import.c:904 +#: g10/import.c:930 #, c-format msgid "key %s: doesn't match our copy\n" msgstr "Schl?ssel %s: Stimmt nicht mit unserer Kopie ?berein\n" -#: g10/import.c:921 g10/import.c:1541 +#: g10/import.c:947 g10/import.c:1567 #, c-format msgid "key %s: can't locate original keyblock: %s\n" msgstr "Schl?ssel %s: der originale Schl?sselblock wurde nicht gefunden: %s\n" -#: g10/import.c:929 g10/import.c:1548 +#: g10/import.c:955 g10/import.c:1574 #, c-format msgid "key %s: can't read original keyblock: %s\n" msgstr "Schl?ssel %s: Lesefehler im originalen Schl?sselblock: %s\n" -#: g10/import.c:971 +#: g10/import.c:997 #, c-format msgid "key %s: \"%s\" 1 new user ID\n" msgstr "Schl?ssel %s: \"%s\" 1 neue User-ID\n" -#: g10/import.c:974 +#: g10/import.c:1000 #, c-format msgid "key %s: \"%s\" %d new user IDs\n" msgstr "Schl?ssel %s: \"%s\" %d neue User-IDs\n" -#: g10/import.c:977 +#: g10/import.c:1003 #, c-format msgid "key %s: \"%s\" 1 new signature\n" msgstr "Schl?ssel %s: \"%s\" 1 neue Signatur\n" -#: g10/import.c:980 +#: g10/import.c:1006 #, c-format msgid "key %s: \"%s\" %d new signatures\n" msgstr "Schl?ssel %s: \"%s\" %d neue Signaturen\n" -#: g10/import.c:983 +#: g10/import.c:1009 #, c-format msgid "key %s: \"%s\" 1 new subkey\n" msgstr "Schl?ssel %s: \"%s\" 1 neuer Unterschl?ssel\n" -#: g10/import.c:986 +#: g10/import.c:1012 #, c-format msgid "key %s: \"%s\" %d new subkeys\n" msgstr "Schl?ssel %s: \"%s\" %d neue Unterschl?ssel\n" -#: g10/import.c:989 +#: g10/import.c:1015 #, c-format msgid "key %s: \"%s\" %d signature cleaned\n" msgstr "Schl?ssel %s: \"%s\" %d Signaturen bereinigt\n" -#: g10/import.c:992 +#: g10/import.c:1018 #, c-format msgid "key %s: \"%s\" %d signatures cleaned\n" msgstr "Schl?ssel %s: \"%s\" %d Signaturen bereinigt\n" -#: g10/import.c:995 +#: g10/import.c:1021 #, c-format msgid "key %s: \"%s\" %d user ID cleaned\n" msgstr "Schl?ssel %s: \"%s\" %d User-ID bereinigt\n" -#: g10/import.c:998 +#: g10/import.c:1024 #, c-format msgid "key %s: \"%s\" %d user IDs cleaned\n" msgstr "Schl?ssel %s: \"%s\" %d User-IDs bereinigt\n" -#: g10/import.c:1021 +#: g10/import.c:1047 #, c-format msgid "key %s: \"%s\" not changed\n" msgstr "Schl?ssel %s: \"%s\" nicht ge?ndert\n" -#: g10/import.c:1275 g10/import.c:1468 +#: g10/import.c:1301 g10/import.c:1494 #, c-format msgid "key %s: secret key imported\n" msgstr "Schl?ssel %s: geheimer Schl?ssel importiert\n" -#: g10/import.c:1282 +#: g10/import.c:1308 #, c-format msgid "key %s: secret key already exists\n" msgstr "Schl?ssel %s: geheimer Schl?ssel bereits vorhanden\n" -#: g10/import.c:1289 +#: g10/import.c:1315 #, c-format msgid "key %s: error sending to agent: %s\n" msgstr "Schl?ssel %s: Fehler beim Senden zum gpg-agent: %s\n" -#: g10/import.c:1419 +#: g10/import.c:1445 #, c-format msgid "key %s: secret key with invalid cipher %d - skipped\n" msgstr "" "Schl?ssel %s: geheimer Schl?ssel mit ung?ltiger Verschl?sselung %d - " "?bersprungen\n" -#: g10/import.c:1430 +#: g10/import.c:1456 msgid "importing secret keys not allowed\n" msgstr "Importieren geheimer Schl?ssel ist nicht erlaubt\n" -#: g10/import.c:1481 +#: g10/import.c:1507 #, c-format msgid "key %s: secret key part already available\n" msgstr "Schl?ssel %s: Die geheimen Teile sind bereits vorhanden\n" -#: g10/import.c:1516 +#: g10/import.c:1542 #, c-format msgid "key %s: no public key - can't apply revocation certificate\n" msgstr "" "Schl?ssel %s: Kein ?ffentlicher Schl?ssel - der Schl?sselwiderruf kann nicht " "angebracht werden\n" -#: g10/import.c:1559 +#: g10/import.c:1585 #, c-format msgid "key %s: invalid revocation certificate: %s - rejected\n" msgstr "Schl?ssel %s: Ung?ltiges Widerrufzertifikat: %s - zur?ckgewiesen\n" -#: g10/import.c:1591 +#: g10/import.c:1617 #, c-format msgid "key %s: \"%s\" revocation certificate imported\n" msgstr "Schl?ssel %s: \"%s\" Widerrufzertifikat importiert\n" -#: g10/import.c:1667 +#: g10/import.c:1693 #, c-format msgid "key %s: no user ID for signature\n" msgstr "Schl?ssel %s: Keine User-ID f?r Signatur\n" -#: g10/import.c:1684 +#: g10/import.c:1710 #, c-format msgid "key %s: unsupported public key algorithm on user ID \"%s\"\n" msgstr "" "Schl?ssel %s: Nicht unterst?tztes Public-Key-Verfahren f?r User-ID \"%s\"\n" -#: g10/import.c:1686 +#: g10/import.c:1712 #, c-format msgid "key %s: invalid self-signature on user ID \"%s\"\n" msgstr "Schl?ssel %s: Ung?ltige Eigenbeglaubigung f?r User-ID \"%s\"\n" -#: g10/import.c:1703 g10/import.c:1729 g10/import.c:1780 +#: g10/import.c:1729 g10/import.c:1755 g10/import.c:1806 #, c-format msgid "key %s: unsupported public key algorithm\n" msgstr "Schl?ssel %s: Nicht unterst?tztes Public-Key-Verfahren\n" -#: g10/import.c:1704 +#: g10/import.c:1730 #, c-format msgid "key %s: invalid direct key signature\n" msgstr "Schl?ssel %s: Ung?ltige \"direct-key\"-Signatur\n" -#: g10/import.c:1718 +#: g10/import.c:1744 #, c-format msgid "key %s: no subkey for key binding\n" msgstr "Schl?ssel %s: Kein Unterschl?ssel f?r die Unterschl?sselanbindung\n" -#: g10/import.c:1731 +#: g10/import.c:1757 #, c-format msgid "key %s: invalid subkey binding\n" msgstr "Schl?ssel %s: Ung?ltige Unterschl?ssel-Anbindung\n" -#: g10/import.c:1747 +#: g10/import.c:1773 #, c-format msgid "key %s: removed multiple subkey binding\n" msgstr "Schl?ssel %s: Mehrfache Unterschl?ssel-Anbindung entfernt\n" -#: g10/import.c:1769 +#: g10/import.c:1795 #, c-format msgid "key %s: no subkey for key revocation\n" msgstr "Schl?ssel %s: Kein Unterschl?ssel f?r Schl?sselwiderruf\n" -#: g10/import.c:1782 +#: g10/import.c:1808 #, c-format msgid "key %s: invalid subkey revocation\n" msgstr "Schl?ssel %s: Ung?ltiger Unterschl?sselwiderruf\n" -#: g10/import.c:1797 +#: g10/import.c:1823 #, c-format msgid "key %s: removed multiple subkey revocation\n" msgstr "Schl?ssel %s: Mehrfacher Unterschl?sselwiderruf entfernt\n" -#: g10/import.c:1839 +#: g10/import.c:1865 #, c-format msgid "key %s: skipped user ID \"%s\"\n" msgstr "Schl?ssel %s: User-ID ?bersprungen \"%s\"\n" -#: g10/import.c:1860 +#: g10/import.c:1886 #, c-format msgid "key %s: skipped subkey\n" msgstr "Schl?ssel %s: Unterschl?ssel ?bersprungen\n" -#: g10/import.c:1887 +#: g10/import.c:1913 #, c-format msgid "key %s: non exportable signature (class 0x%02X) - skipped\n" msgstr "" "Schl?ssel %s: Nicht exportf?hige Signatur (Klasse %02x) - ?bersprungen\n" -#: g10/import.c:1897 +#: g10/import.c:1923 #, c-format msgid "key %s: revocation certificate at wrong place - skipped\n" msgstr "Schl?ssel %s: Widerrufzertifikat an falschem Platz - ?bersprungen\n" -#: g10/import.c:1914 +#: g10/import.c:1940 #, c-format msgid "key %s: invalid revocation certificate: %s - skipped\n" msgstr "Schl?ssel %s: Ung?ltiges Widerrufzertifikat: %s - ?bersprungen\n" -#: g10/import.c:1928 +#: g10/import.c:1954 #, c-format msgid "key %s: subkey signature in wrong place - skipped\n" msgstr "" "Schl?ssel %s: Unterschl?ssel-Widerrufzertifikat an falschem Platz - " "?bersprungen\n" -#: g10/import.c:1936 +#: g10/import.c:1962 #, c-format msgid "key %s: unexpected signature class (0x%02X) - skipped\n" msgstr "Schl?ssel %s: unerwartete Signaturklasse (0x%02x) - ?bersprungen\n" -#: g10/import.c:2065 +#: g10/import.c:2091 #, c-format msgid "key %s: duplicated user ID detected - merged\n" msgstr "Schl?ssel %s: Doppelte User-ID entdeckt - zusammengef?hrt\n" -#: g10/import.c:2127 +#: g10/import.c:2153 #, c-format msgid "WARNING: key %s may be revoked: fetching revocation key %s\n" msgstr "WARNUNG: Schl?ssel %s ist u.U. widerrufen: hole Widerrufschl?ssel %s\n" -#: g10/import.c:2142 +#: g10/import.c:2168 #, c-format msgid "WARNING: key %s may be revoked: revocation key %s not present.\n" msgstr "" "WARNUNG: Schl?ssel %s ist u.U. widerrufen: Widerrufschl?ssel %s ist nicht " "vorhanden\n" -#: g10/import.c:2201 +#: g10/import.c:2227 #, c-format msgid "key %s: \"%s\" revocation certificate added\n" msgstr "Schl?ssel %s: \"%s\" Widerrufzertifikat hinzugef?gt\n" -#: g10/import.c:2235 +#: g10/import.c:2261 #, c-format msgid "key %s: direct key signature added\n" msgstr "Schl?ssel %s: \"direct-key\"-Signaturen hinzugef?gt\n" @@ -4048,7 +4048,7 @@ msgstr "" msgid "(sensitive)" msgstr "(empfindlich)" -#: g10/keyedit.c:2775 g10/keyedit.c:2888 g10/keyserver.c:552 +#: g10/keyedit.c:2775 g10/keyedit.c:2888 g10/keyserver.c:557 #, c-format msgid "created: %s" msgstr "erzeugt: %s" @@ -4064,7 +4064,7 @@ msgid "expired: %s" msgstr "verfallen: %s" #: g10/keyedit.c:2782 g10/keyedit.c:2890 g10/keylist.c:822 g10/keylist.c:945 -#: g10/keyserver.c:558 g10/mainproc.c:1014 +#: g10/keyserver.c:563 g10/mainproc.c:1014 #, c-format msgid "expires: %s" msgstr "verf?llt: %s" @@ -4100,13 +4100,13 @@ msgstr "" "Bitte beachten Sie, da? ohne einen Programmneustart die angezeigte\n" "Schl?sselg?ltigkeit nicht notwendigerweise korrekt ist.\n" -#: g10/keyedit.c:2907 g10/keyedit.c:3219 g10/keyserver.c:562 +#: g10/keyedit.c:2907 g10/keyedit.c:3219 g10/keyserver.c:567 #: g10/mainproc.c:1874 g10/trustdb.c:1202 g10/trustdb.c:1731 #: dirmngr/ocsp.c:699 msgid "revoked" msgstr "widerrufen" -#: g10/keyedit.c:2909 g10/keyedit.c:3221 g10/keyserver.c:566 +#: g10/keyedit.c:2909 g10/keyedit.c:3221 g10/keyserver.c:571 #: g10/mainproc.c:1876 g10/trustdb.c:549 g10/trustdb.c:1733 msgid "expired" msgstr "verfallen" @@ -4975,179 +4975,122 @@ msgstr "%lu Schl?ssel gepuffert (%lu Beglaubigungen)\n" msgid "%s: keyring created\n" msgstr "%s: Schl?sselbund erstellt\n" -#: g10/keyserver.c:94 +#: g10/keyserver.c:97 msgid "include revoked keys in search results" msgstr "Widerrufene Schl?ssel in den Suchergebnissen auff?hren" -#: g10/keyserver.c:95 +#: g10/keyserver.c:98 msgid "include subkeys when searching by key ID" msgstr "Unterschl?ssel in der Suche ?ber Schl?ssel-IDs auff?hren" -#: g10/keyserver.c:97 +#: g10/keyserver.c:100 msgid "use temporary files to pass data to keyserver helpers" msgstr "" "verwende tempor?re Dateien, um Daten an die Schl?sselserverhilfsprogramme zu " "geben" -#: g10/keyserver.c:99 +#: g10/keyserver.c:102 msgid "do not delete temporary files after using them" msgstr "Tempor?re Dateien nach Nutzung nicht l?schen" -#: g10/keyserver.c:103 +#: g10/keyserver.c:106 msgid "automatically retrieve keys when verifying signatures" msgstr "Schl?ssel f?r die Signaturpr?fung automatisch holen" -#: g10/keyserver.c:105 +#: g10/keyserver.c:108 msgid "honor the preferred keyserver URL set on the key" msgstr "" "Die im Schl?ssel enthaltene bevorzugte URL f?r Schl?sselserver beachten" -#: g10/keyserver.c:107 +#: g10/keyserver.c:110 msgid "honor the PKA record set on a key when retrieving keys" msgstr "Die im Schl?ssel enthaltenen PKA-Daten beim Schl?sselholen beachten" -#: g10/keyserver.c:173 +#: g10/keyserver.c:178 #, c-format msgid "WARNING: keyserver option `%s' is not used on this platform\n" msgstr "" "WARNUNG: Schl?sselserver-Option `%s' wird auf dieser Plattform nicht " "verwendet\n" -#: g10/keyserver.c:564 +#: g10/keyserver.c:569 msgid "disabled" msgstr "abgeschaltet" -#: g10/keyserver.c:764 +#: g10/keyserver.c:773 msgid "Enter number(s), N)ext, or Q)uit > " msgstr "Eingabe von Nummern, N?chste (N) oder Abbrechen (Q) > " -#: g10/keyserver.c:834 g10/keyserver.c:1471 +#: g10/keyserver.c:867 #, c-format msgid "invalid keyserver protocol (us %d!=handler %d)\n" msgstr "Ung?ltiges Schl?sselserverprotokoll (wir %d!=Handhabungsroutine %d)\n" -#: g10/keyserver.c:1190 -#, c-format -msgid "requesting key %s from %s server %s\n" -msgstr "fordere Schl?ssel %s von %s-Server %s an\n" - -#: g10/keyserver.c:1194 -#, c-format -msgid "requesting key %s from %s\n" -msgstr "fordere Schl?ssel %s von %s an\n" - -#: g10/keyserver.c:1218 -#, c-format -msgid "searching for names from %s server %s\n" -msgstr "suche Namen auf %s-Server %s\n" - -#: g10/keyserver.c:1221 -#, c-format -msgid "searching for names from %s\n" -msgstr "suche Namen auf %s\n" - -#: g10/keyserver.c:1374 +#: g10/keyserver.c:1008 g10/keyserver.c:1043 #, c-format -msgid "sending key %s to %s server %s\n" -msgstr "sende Schl?ssel %s auf den %s-Server %s\n" - -#: g10/keyserver.c:1378 -#, c-format -msgid "sending key %s to %s\n" -msgstr "sende Schl?ssel %s auf %s\n" +msgid "\"%s\" not a key ID: skipping\n" +msgstr "\"%s\" ist keine Schl?ssel-ID: ?berspringe\n" -#: g10/keyserver.c:1421 +#: g10/keyserver.c:1303 #, c-format -msgid "searching for \"%s\" from %s server %s\n" -msgstr "suche nach \"%s\" auf %s-Server %s\n" +msgid "WARNING: unable to refresh key %s via %s: %s\n" +msgstr "WARNUNG: Schl?ssel %s kann per %s nicht aktualisiert werden: %s\n" -#: g10/keyserver.c:1424 +#: g10/keyserver.c:1325 #, c-format -msgid "searching for \"%s\" from %s\n" -msgstr "suche nach \"%s\" auf %s\n" - -#: g10/keyserver.c:1431 g10/keyserver.c:1528 -msgid "no keyserver action!\n" -msgstr "Kein Schl?sselserver-Vorgang\n" +msgid "refreshing 1 key from %s\n" +msgstr "ein Schl?ssel wird per %s aktualisiert\n" -#: g10/keyserver.c:1479 +#: g10/keyserver.c:1327 #, c-format -msgid "WARNING: keyserver handler from a different version of GnuPG (%s)\n" -msgstr "" -"WARNUNG: Die Schl?sselserver-Handhabungsroutine stammt von einer anderen " -"GnuPG-Version (%s)\n" - -#: g10/keyserver.c:1488 -msgid "keyserver did not send VERSION\n" -msgstr "Schl?sselserver sendete VERSION nicht\n" +msgid "refreshing %d keys from %s\n" +msgstr "%d Schl?ssel werden per %s aktualisiert\n" -#: g10/keyserver.c:1553 g10/keyserver.c:1983 g10/keyserver.c:2180 +#: g10/keyserver.c:1363 g10/keyserver.c:1415 g10/keyserver.c:1604 +#: g10/keyserver.c:1754 msgid "no keyserver known (use option --keyserver)\n" msgstr "Kein Schl?sselserver bekannt (Option --keyserver verwenden)\n" -#: g10/keyserver.c:1565 +#: g10/keyserver.c:1408 #, c-format -msgid "no handler for keyserver scheme `%s'\n" -msgstr "Keine Handhabungsroutine f?r Schl?sselserverschema `%s'\n" - -#: g10/keyserver.c:1570 -#, c-format -msgid "action `%s' not supported with keyserver scheme `%s'\n" -msgstr "Vorgang `%s' wird vom Schl?sselserverschema `%s' nicht unterst?tzt\n" - -#: g10/keyserver.c:1578 -#, c-format -msgid "%s does not support handler version %d\n" -msgstr "%s unterst?tzt Hilfsroutinenversion %d nicht\n" - -#: g10/keyserver.c:1585 -msgid "keyserver timed out\n" -msgstr "Schl?sselserver-Zeit?berschreitung\n" - -#: g10/keyserver.c:1590 -msgid "keyserver internal error\n" -msgstr "interner Fehler Schl?sselserver\n" +msgid "key \"%s\" not found on keyserver\n" +msgstr "Schl?ssel \"%s\" wurde auf dem Schl?sselserver nicht gefunden\n" -#: g10/keyserver.c:1599 -#, c-format -msgid "keyserver communications error: %s\n" -msgstr "Schl?sselserver-Daten?bertragunsfehler: %s\n" +#: g10/keyserver.c:1411 +msgid "key not found on keyserver\n" +msgstr "Schl?ssel wurde auf dem Schl?sselserver nicht gefunden\n" -#: g10/keyserver.c:1624 g10/keyserver.c:1659 +#: g10/keyserver.c:1548 #, c-format -msgid "\"%s\" not a key ID: skipping\n" -msgstr "\"%s\" ist keine Schl?ssel-ID: ?berspringe\n" +msgid "requesting key %s from %s server %s\n" +msgstr "fordere Schl?ssel %s von %s-Server %s an\n" -#: g10/keyserver.c:1922 +#: g10/keyserver.c:1552 #, c-format -msgid "WARNING: unable to refresh key %s via %s: %s\n" -msgstr "WARNUNG: Schl?ssel %s kann per %s nicht aktualisiert werden: %s\n" +msgid "requesting key %s from %s\n" +msgstr "fordere Schl?ssel %s von %s an\n" -#: g10/keyserver.c:1944 +#: g10/keyserver.c:1618 g10/skclist.c:191 g10/skclist.c:219 #, c-format -msgid "refreshing 1 key from %s\n" -msgstr "ein Schl?ssel wird per %s aktualisiert\n" +msgid "skipped \"%s\": %s\n" +msgstr "?bersprungen \"%s\": %s\n" -#: g10/keyserver.c:1946 +#: g10/keyserver.c:1622 #, c-format -msgid "refreshing %d keys from %s\n" -msgstr "%d Schl?ssel werden per %s aktualisiert\n" +msgid "sending key %s to %s server %s\n" +msgstr "sende Schl?ssel %s auf den %s-Server %s\n" -#: g10/keyserver.c:2028 +#: g10/keyserver.c:1626 #, c-format -msgid "key \"%s\" not found on keyserver\n" -msgstr "Schl?ssel \"%s\" wurde auf dem Schl?sselserver nicht gefunden\n" - -#: g10/keyserver.c:2031 -msgid "key not found on keyserver\n" -msgstr "Schl?ssel wurde auf dem Schl?sselserver nicht gefunden\n" +msgid "sending key %s to %s\n" +msgstr "sende Schl?ssel %s auf %s\n" -#: g10/keyserver.c:2099 +#: g10/keyserver.c:1673 #, c-format msgid "WARNING: unable to fetch URI %s: %s\n" msgstr "WARNUNG: die URI %s kann nicht geholt werden: %s\n" -#: g10/keyserver.c:2105 +#: g10/keyserver.c:1679 #, c-format msgid "WARNING: unable to parse URI %s\n" msgstr "WARNUNG: die URI %s kann nicht analysiert werden\n" @@ -6266,11 +6209,6 @@ msgstr "" msgid "skipped \"%s\": duplicated\n" msgstr "?bersprungen \"%s\": doppelt\n" -#: g10/skclist.c:191 g10/skclist.c:219 -#, c-format -msgid "skipped \"%s\": %s\n" -msgstr "?bersprungen \"%s\": %s\n" - #: g10/skclist.c:201 msgid "skipped: secret key already present\n" msgstr "?bersprungen: geheimer Schl?ssel bereits vorhanden\n" @@ -8706,7 +8644,7 @@ msgstr "Erhielt Status: `%s'\n" msgid "error writing base64 encoding: %s\n" msgstr "Fehler beim Schreiben der Base-64 Darstellung: %s\n" -#: dirmngr/dirmngr-client.c:453 dirmngr/server.c:1672 +#: dirmngr/dirmngr-client.c:453 dirmngr/server.c:1804 #, c-format msgid "failed to allocate assuan context: %s\n" msgstr "Fehler beim Bereitstellen eines Assuan Kontext: %s\n" @@ -8883,12 +8821,12 @@ msgstr "Gebrauch: dirmngr [Optionen] " msgid "colons are not allowed in the socket name\n" msgstr "Doppelpunkte sind im Namen des Sockets nicht erlaubt\n" -#: dirmngr/dirmngr.c:1164 dirmngr/server.c:1179 +#: dirmngr/dirmngr.c:1164 dirmngr/server.c:1185 #, c-format msgid "fetching CRL from `%s' failed: %s\n" msgstr "Holen der CRL von `%s' fehlgeschlagen: %s\n" -#: dirmngr/dirmngr.c:1170 dirmngr/server.c:1185 +#: dirmngr/dirmngr.c:1170 dirmngr/server.c:1191 #, c-format msgid "processing CRL from `%s' failed: %s\n" msgstr "Verarbeitung der CRL von `%s' fehlgeschlagen: %s\n" @@ -9377,71 +9315,71 @@ msgstr "OCSP Responder gab einen nicht aktuellen Status zur?ck\n" msgid "OCSP responder returned an too old status\n" msgstr "OCSP Responder gab einen zu alten Status zur?ck\n" -#: dirmngr/server.c:285 dirmngr/server.c:397 dirmngr/server.c:443 +#: dirmngr/server.c:291 dirmngr/server.c:403 dirmngr/server.c:449 #, c-format msgid "assuan_inquire(%s) failed: %s\n" msgstr "assuan_inquire(%s) fehlgeschlagen: %s\n" -#: dirmngr/server.c:540 +#: dirmngr/server.c:546 msgid "ldapserver missing" msgstr "LDAP Server fehlt" -#: dirmngr/server.c:610 +#: dirmngr/server.c:616 msgid "serialno missing in cert ID" msgstr "Seriennummer fehlt in der Cert-ID" -#: dirmngr/server.c:746 dirmngr/server.c:832 dirmngr/server.c:1264 -#: dirmngr/server.c:1315 +#: dirmngr/server.c:752 dirmngr/server.c:838 dirmngr/server.c:1270 +#: dirmngr/server.c:1321 dirmngr/server.c:1578 dirmngr/server.c:1594 #, c-format msgid "assuan_inquire failed: %s\n" msgstr "assuan_inquire fehlgeschlagen: %s\n" -#: dirmngr/server.c:875 +#: dirmngr/server.c:881 #, c-format msgid "fetch_cert_by_url failed: %s\n" msgstr "fetch_cert_by_url() fehlgeschlagen: %s\n" -#: dirmngr/server.c:887 dirmngr/server.c:918 dirmngr/server.c:1074 +#: dirmngr/server.c:893 dirmngr/server.c:924 dirmngr/server.c:1080 #, c-format msgid "error sending data: %s\n" msgstr "Fehler beim Senden der Daten: %s\n" -#: dirmngr/server.c:1022 +#: dirmngr/server.c:1028 #, c-format msgid "start_cert_fetch failed: %s\n" msgstr "start_cert_fetch fehlgeschlagen: %s\n" -#: dirmngr/server.c:1055 +#: dirmngr/server.c:1061 #, c-format msgid "fetch_next_cert failed: %s\n" msgstr "fetch_next_cert fehlgeschlagen: %s\n" -#: dirmngr/server.c:1082 +#: dirmngr/server.c:1088 #, c-format msgid "max_replies %d exceeded\n" msgstr "max_replies %d ?berschritten\n" -#: dirmngr/server.c:1661 +#: dirmngr/server.c:1793 #, c-format msgid "can't allocate control structure: %s\n" msgstr "Fehler beim Erzeugen der Kontrollstruktur: %s\n" -#: dirmngr/server.c:1693 +#: dirmngr/server.c:1825 #, c-format msgid "failed to initialize the server: %s\n" msgstr "Fehler beim Initialisieren des Servers: %s\n" -#: dirmngr/server.c:1701 +#: dirmngr/server.c:1833 #, c-format msgid "failed to the register commands with Assuan: %s\n" msgstr "Fehler beim Registrieren der Kommandos gegen Assuan: %s\n" -#: dirmngr/server.c:1741 +#: dirmngr/server.c:1873 #, c-format msgid "Assuan accept problem: %s\n" msgstr "Assuan accept Problem: %s\n" -#: dirmngr/server.c:1760 +#: dirmngr/server.c:1892 #, c-format msgid "Assuan processing failed: %s\n" msgstr "Assuan Verarbeitung fehlgeschlagen: %s\n" @@ -9971,6 +9909,48 @@ msgstr "" "Syntax: gpg-check-pattern [optionen] Musterdatei\n" "Die von stdin gelesene Passphrase gegen die Musterdatei pr?fen\n" +#~ msgid "searching for names from %s server %s\n" +#~ msgstr "suche Namen auf %s-Server %s\n" + +#~ msgid "searching for names from %s\n" +#~ msgstr "suche Namen auf %s\n" + +#~ msgid "searching for \"%s\" from %s server %s\n" +#~ msgstr "suche nach \"%s\" auf %s-Server %s\n" + +#~ msgid "searching for \"%s\" from %s\n" +#~ msgstr "suche nach \"%s\" auf %s\n" + +#~ msgid "no keyserver action!\n" +#~ msgstr "Kein Schl?sselserver-Vorgang\n" + +#~ msgid "WARNING: keyserver handler from a different version of GnuPG (%s)\n" +#~ msgstr "" +#~ "WARNUNG: Die Schl?sselserver-Handhabungsroutine stammt von einer anderen " +#~ "GnuPG-Version (%s)\n" + +#~ msgid "keyserver did not send VERSION\n" +#~ msgstr "Schl?sselserver sendete VERSION nicht\n" + +#~ msgid "no handler for keyserver scheme `%s'\n" +#~ msgstr "Keine Handhabungsroutine f?r Schl?sselserverschema `%s'\n" + +#~ msgid "action `%s' not supported with keyserver scheme `%s'\n" +#~ msgstr "" +#~ "Vorgang `%s' wird vom Schl?sselserverschema `%s' nicht unterst?tzt\n" + +#~ msgid "%s does not support handler version %d\n" +#~ msgstr "%s unterst?tzt Hilfsroutinenversion %d nicht\n" + +#~ msgid "keyserver timed out\n" +#~ msgstr "Schl?sselserver-Zeit?berschreitung\n" + +#~ msgid "keyserver internal error\n" +#~ msgstr "interner Fehler Schl?sselserver\n" + +#~ msgid "keyserver communications error: %s\n" +#~ msgstr "Schl?sselserver-Daten?bertragunsfehler: %s\n" + #~ msgid "connection to agent established (%ds)\n" #~ msgstr "Verbindung zum gpg-agent aufgebaut (%ds)\n" ----------------------------------------------------------------------- Summary of changes: ChangeLog | 4 + NEWS | 3 + common/ChangeLog | 11 ++ common/http.c | 27 ++- configure.ac | 8 +- po/ChangeLog | 4 + po/de.po | 468 ++++++++++++++++++++++++++---------------------------- 7 files changed, 269 insertions(+), 256 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Thu Jan 20 16:09:11 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Thu, 20 Jan 2011 16:09:11 +0100 Subject: [git] GnuPG - branch, STABLE-BRANCH-2-0, updated. gnupg-2.0.16-31-gabceb05 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, STABLE-BRANCH-2-0 has been updated via abceb05d5432dcb25e25db908b1ce55ad964cf9e (commit) from 846d5744078bef2d781c0847cd5686f8c5016b40 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit abceb05d5432dcb25e25db908b1ce55ad964cf9e Author: Werner Koch Date: Thu Jan 20 15:49:20 2011 +0100 Fix a bug in es_fopenmem etc. diff --git a/common/ChangeLog b/common/ChangeLog index eb1f22e..7025966 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -1,6 +1,10 @@ +2011-01-20 Werner Koch + + * estream.c (es_func_mem_write): Fix computation of NEWSIZE. + 2011-01-11 Werner Koch - Estream changes as used gnupg master from 2010-07-19. + Estream changes as used by gnupg master from 2010-07-19. * estream.c (es_fname_get, es_fname_set): New. (fname_set_internal): New. diff --git a/common/estream.c b/common/estream.c index 3ab68b5..9f7dfd0 100644 --- a/common/estream.c +++ b/common/estream.c @@ -497,7 +497,7 @@ typedef struct estream_cookie_mem /* Create function for memory objects. DATA is either NULL or a user - supplied buffer with the initial conetnt of the memory buffer. If + supplied buffer with the initial content of the memory buffer. If DATA is NULL, DATA_N and DATA_LEN need to be 0 as well. If DATA is not NULL, DATA_N gives the allocated size of DATA and DATA_LEN the used length in DATA. */ @@ -596,7 +596,7 @@ es_func_mem_write (void *cookie, const void *buffer, size_t size) if (!mem_cookie->memory_size) newsize = size; /* Not yet allocated. */ else - newsize = mem_cookie->memory_size + (nleft - size); + newsize = mem_cookie->memory_size + (size - nleft); if (newsize < mem_cookie->offset) { _set_errno (EINVAL); ----------------------------------------------------------------------- Summary of changes: common/ChangeLog | 6 +++++- common/estream.c | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Thu Jan 20 19:12:43 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Thu, 20 Jan 2011 19:12:43 +0100 Subject: [git] GCRYPT - branch, ECC-INTEGRATION-1-5, updated. libgcrypt-1.4.4-54-gdef2727 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, ECC-INTEGRATION-1-5 has been updated via def2727f8bee594b2b51863391296468813c604b (commit) via 54f50ea4d1e5d0e94d8cc16ed777fca88b076ee4 (commit) from 94760660ab77bab25b24d67f8e813f1b49d35e07 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit def2727f8bee594b2b51863391296468813c604b Author: Werner Koch Date: Thu Jan 20 18:50:29 2011 +0100 Editorial changes. Adjusted indentation to GNU style. Replaced C++ style comments. Reformatted some comments. diff --git a/cipher/ecc.c b/cipher/ecc.c index a7a5554..aa0cd6a 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -1,18 +1,18 @@ /* ecc.c - Elliptic Curve Cryptography - Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc. + Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc. This file is part of Libgcrypt. - + Libgcrypt is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + Libgcrypt is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, @@ -60,6 +60,7 @@ #include "cipher.h" #include +/* The maximum length of our DER encoded OID. */ #define MAX_ECC_OID_LEN 16 /* Definition of a curve. */ @@ -70,11 +71,11 @@ typedef struct gcry_mpi_t b; /* Second coefficient of the Weierstrass equation. */ mpi_point_t G; /* Base point (generator). */ gcry_mpi_t n; /* Order of G. */ - /* one byte length, followed by DER representation of curve OID: - * N byte OID is encoded as N+1 bytes as follows: N x0 x1 ... xN - */ - byte name_oid[MAX_ECC_OID_LEN]; -} elliptic_curve_t; + + /* One byte length, followed by DER representation of curve OID: + * N byte OID is encoded as N+1 bytes as follows: N x0 x1 ... xN. */ + byte name_oid[MAX_ECC_OID_LEN]; +} elliptic_curve_t; typedef struct @@ -96,7 +97,7 @@ static const struct { const char *name; /* Our name. */ const char *other; /* Other name. */ -} curve_aliases[] = +} curve_aliases[] = { { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID */ { "NIST P-192", "prime192v1" }, /* X9.62 name. */ @@ -106,11 +107,11 @@ static const struct { "NIST P-224", "1.3.132.0.33" }, /* SECP OID. */ { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1. */ - { "NIST P-256", "prime256v1" }, + { "NIST P-256", "prime256v1" }, { "NIST P-256", "secp256r1" }, { "NIST P-384", "secp384r1" }, - { "NIST P-384", "1.3.132.0.34" }, + { "NIST P-384", "1.3.132.0.34" }, { "NIST P-521", "secp521r1" }, { "NIST P-521", "1.3.132.0.35" }, @@ -126,9 +127,12 @@ static const struct { NULL, NULL} }; -static const byte curve_oid_NISTP256[] = { 8, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07 }; -static const byte curve_oid_NISTP384[] = { 5, 0x2B, 0x81, 0x04, 0x00, 0x22 }; -static const byte curve_oid_NISTP521[] = { 5, 0x2B, 0x81, 0x04, 0x00, 0x23 }; +static const byte curve_oid_NISTP256[] = + { 8, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07 }; +static const byte curve_oid_NISTP384[] = + { 5, 0x2B, 0x81, 0x04, 0x00, 0x22 }; +static const byte curve_oid_NISTP521[] = + { 5, 0x2B, 0x81, 0x04, 0x00, 0x23 }; typedef struct { const char *desc; /* Description of the curve. */ @@ -359,23 +363,30 @@ curve_free (elliptic_curve_t *E) mpi_free (E->n); E->n = NULL; } + /* * Release a PK object. */ -static void ecc_pk_free( ECC_public_key *pk ) { +static void +ecc_pk_free (ECC_public_key *pk) +{ point_free (&pk->Q); curve_free (&pk->E); } + /* * Release a SK object. */ -static void ecc_sk_free( ECC_secret_key *sk ) { +static void +ecc_sk_free (ECC_secret_key *sk) +{ point_free (&sk->Q); curve_free (&sk->E); mpi_free (sk->d); sk->d = NULL; } + /* * Return a copy of a curve object. */ @@ -395,7 +406,6 @@ curve_copy (elliptic_curve_t E) } - /* Helper to scan a hex string. */ static gcry_mpi_t scanval (const char *string) @@ -426,10 +436,10 @@ gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base) axb = mpi_new (0); y = mpi_new (0); - mpi_powm (x_3, x, three, base->p); - mpi_mulm (axb, base->a, x, base->p); - mpi_addm (axb, axb, base->b, base->p); - mpi_addm (y, x_3, axb, base->p); + mpi_powm (x_3, x, three, base->p); + mpi_mulm (axb, base->a, x, base->p); + mpi_addm (axb, axb, base->b, base->p); + mpi_addm (y, x_3, axb, base->p); mpi_free (x_3); mpi_free (axb); @@ -438,9 +448,6 @@ gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base) } - - - /* Generate a random secret scalar k with an order of p At the beginning this was identical to the code is in elgamal.c. @@ -463,13 +470,12 @@ gen_k (gcry_mpi_t p, int security_level) return k; } -/**************** - * Generate the crypto system setup. - * As of now the fix NIST recommended values are used. - * The subgroup generator point is in another function: gen_big_point. - */ + +/* Generate the crypto system setup. As of now the fix NIST + recommended values are used. The subgroup generator point is in + another function: gen_big_point. */ static gpg_err_code_t -generate_curve (unsigned int nbits, const char *name, +generate_curve (unsigned int nbits, const char *name, elliptic_curve_t *curve, unsigned int *r_nbits) { int idx, aliasno; @@ -508,8 +514,8 @@ generate_curve (unsigned int nbits, const char *name, possible to bypass this check by specifying the curve parameters directly. */ if (fips_mode () && !domain_parms[idx].fips ) - return GPG_ERR_NOT_SUPPORTED; - + return GPG_ERR_NOT_SUPPORTED; + *r_nbits = domain_parms[idx].nbits; curve->p = scanval (domain_parms[idx].p); @@ -519,9 +525,10 @@ generate_curve (unsigned int nbits, const char *name, curve->G.x = scanval (domain_parms[idx].g_x); curve->G.y = scanval (domain_parms[idx].g_y); curve->G.z = mpi_alloc_set_ui (1); - memset( curve->name_oid, 0, sizeof(curve->name_oid) ); - if( domain_parms[idx].name_oid != NULL ) - memcpy( curve->name_oid, domain_parms[idx].name_oid, domain_parms[idx].name_oid[0]+1 ); + memset (curve->name_oid, 0, sizeof(curve->name_oid)); + if (domain_parms[idx].name_oid) + memcpy (curve->name_oid, + domain_parms[idx].name_oid, domain_parms[idx].name_oid[0]+1); return 0; } @@ -557,15 +564,18 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, log_mpidump ("ecgen curve G.x", E.G.x); /* log_mpidump ("ecc generation Gy", E.G.y); log_mpidump ("ecc generation Gz", E.G.z); */ - - log_printf ("ecgen curve OID: [%d] ...%02X %02X\n", E.name_oid[0], E.name_oid[0]>0 ? E.name_oid[E.name_oid[0]-1] : 0, E.name_oid[E.name_oid[0]]); + + log_printf ("ecgen curve OID: [%d] ...%02X %02X\n", + E.name_oid[0], + E.name_oid[0]>0 ? E.name_oid[E.name_oid[0]-1] : 0, + E.name_oid[E.name_oid[0]]); } random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; if (DBG_CIPHER) log_debug ("choosing a random x of size %u%s\n", nbits, transient_key? " (transient-key)":""); - d = gen_k (E.n, random_level); + d = gen_k (E.n, random_level); /* Compute Q. */ point_init (&Q); @@ -603,12 +613,12 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, /* Now we can test our keys (this should never fail!). */ test_keys (sk, nbits - 64); - + return 0; } -/**************** +/* * To verify correct skey it use a random information. * First, encrypt and decrypt this dummy value, * test if the information is recuperated. @@ -657,7 +667,8 @@ test_keys (ECC_secret_key *sk, unsigned int nbits) mpi_free (test); } -/**************** + +/* * To check the validity of the value, recalculate the correspondence * between the public value and the secret one. */ @@ -761,7 +772,7 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s) has to be recomputed. */ mpi_free (k); k = gen_k (skey->E.n, GCRY_STRONG_RANDOM); - _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx); + _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx); if (_gcry_mpi_ec_get_affine (x, NULL, &I, ctx)) { if (DBG_CIPHER) @@ -795,6 +806,7 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s) return err; } + /* * Check if R and S verifies INPUT. */ @@ -891,32 +903,42 @@ verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s) return err; } -/* lookup named curve and fill in internal curve parameters - * returns GPG_ERR_NOT_FOUND for an unknown OID - */ + +/* Lookup named curve and fill in internal curve parameters. Returns + GPG_ERR_NOT_FOUND for an unknown OID. */ static int -fill_in_curve( const byte name_oid[], elliptic_curve_t *curve ) { +fill_in_curve (const byte name_oid[], elliptic_curve_t *curve) +{ int i; const ecc_domain_parms_t *p; - if( name_oid == NULL || name_oid[0] == 0 ) { - log_debug ("ecc OID is malformed\n"); - return GPG_ERR_INV_ARG; - } - for (i = 0; domain_parms[i].desc; i++) { - p = domain_parms + i; - if( p->name_oid == NULL || p->name_oid[0] != name_oid[0] ) - continue; - if ( memcmp( p->name_oid, name_oid, name_oid[0]+1 )==0 ) - break; - } + if (!name_oid || !name_oid[0]) + { + log_debug ("ecc OID is malformed\n"); + return GPG_ERR_INV_ARG; + } - if( ! p->desc ) { - log_debug ("ecc OID is not recognized\n"); - return GPG_ERR_NOT_FOUND; - } + for (i = 0; domain_parms[i].desc; i++) + { + p = domain_parms + i; + if (!p->name_oid || p->name_oid[0] != name_oid[0]) + continue; + if (!memcmp (p->name_oid, name_oid, name_oid[0]+1)) + break; + } + + assert (p); /* FIXME: We need proper error handling. */ + + if (!p->desc) + { + log_debug ("ecc OID is not recognized\n"); + return GPG_ERR_NOT_FOUND; + } - // TODO: there is no reason why these values are encoded as ASCII v.s. binary + /* TODO: there is no reason why these values are encoded as ASCII + v.s. binary. [wk] We might want to put the curve defintions into + a table and use a tool to create them. This also solves the + problem of manuallay encoding the OIDs. */ curve->p = scanval (p->p); curve->a = scanval (p->a); curve->b = scanval (p->b); @@ -926,11 +948,12 @@ fill_in_curve( const byte name_oid[], elliptic_curve_t *curve ) { curve->G.z = mpi_alloc_set_ui (1); if (DBG_CIPHER) - log_debug( "ec filled in curve %s\n", p->desc ); + log_debug ("ec filled in curve %s\n", p->desc); return 0; } + /********************************************* ************** interface ****************** *********************************************/ @@ -963,7 +986,7 @@ ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p) memmove (ptr+(pbytes-n), ptr, n); memset (ptr, 0, (pbytes-n)); } - + err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, buf, 1+2*pbytes, NULL); if (err) log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); @@ -972,14 +995,16 @@ ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p) return result; } + static gcry_mpi_t -name_oid_to_mpi( const byte *name_oid ) { +name_oid_to_mpi (const byte *name_oid) +{ gpg_error_t err; gcry_mpi_t result; - if( name_oid == NULL || name_oid[0] == 0 ) + if (!name_oid || !name_oid[0]) return mpi_new (0); - + err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, name_oid, name_oid[0]+1, NULL); if (err) log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); @@ -987,6 +1012,7 @@ name_oid_to_mpi( const byte *name_oid ) { return result; } + /* RESULT must have been initialized and is set on success to the point given by VALUE. */ static gcry_error_t @@ -1005,7 +1031,7 @@ os2ec (mpi_point_t *result, gcry_mpi_t value) gcry_free (buf); return err; } - if (n < 1) + if (n < 1) { gcry_free (buf); return GPG_ERR_INV_OBJ; @@ -1015,7 +1041,7 @@ os2ec (mpi_point_t *result, gcry_mpi_t value) gcry_free (buf); return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression. */ } - if ( ((n-1)%2) ) + if ( ((n-1)%2) ) { gcry_free (buf); return GPG_ERR_INV_OBJ; @@ -1041,20 +1067,22 @@ os2ec (mpi_point_t *result, gcry_mpi_t value) mpi_free (x); mpi_free (y); - + return 0; } + static gcry_err_code_t -mpi_to_name_oid( gcry_mpi_t mpi_in, byte name_oid_out[MAX_ECC_OID_LEN] ) { +mpi_to_name_oid (gcry_mpi_t mpi_in, byte name_oid_out[MAX_ECC_OID_LEN]) +{ size_t nbytes; unsigned char *buf; gcry_error_t err; - memset( name_oid_out, 0, MAX_ECC_OID_LEN ); + memset (name_oid_out, 0, MAX_ECC_OID_LEN); nbytes = (mpi_get_nbits (mpi_in)+7)/8; - if( nbytes == 0 ) + if (!nbytes) return 0; buf = gcry_xmalloc (nbytes); @@ -1064,17 +1092,18 @@ mpi_to_name_oid( gcry_mpi_t mpi_in, byte name_oid_out[MAX_ECC_OID_LEN] ) { gcry_free (buf); return err; } - if (buf[0]+1 != nbytes || nbytes >= MAX_ECC_OID_LEN) + if (buf[0]+1 != nbytes || nbytes >= MAX_ECC_OID_LEN) { gcry_free (buf); return GPG_ERR_INV_OBJ; } - memcpy( name_oid_out, buf, nbytes+1 ); + memcpy (name_oid_out, buf, nbytes+1); gcry_free (buf); return 0; } + /* Extended version of ecc_generate. */ static gcry_err_code_t ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, @@ -1096,7 +1125,6 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, if (genparms) { - /* Parse the optional "curve" parameter. */ l1 = gcry_sexp_find_token (genparms, "curve", 0); if (l1) @@ -1116,7 +1144,8 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, transient_key = 1; gcry_sexp_release (l1); if (DBG_CIPHER) - log_debug( "ecgen 'transient-key' parameter supplied, value=%d\n", transient_key); + log_debug ("ecgen 'transient-key' parameter supplied, value=%d\n", + transient_key); } /* Parse the "KEK parameters" parameter. */ @@ -1149,20 +1178,25 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, if (ec) return ec; - skey[0] = name_oid_to_mpi( sk.E.name_oid ); // "c", name OID - //if( (ec=fill_in_curve( sk.E.name_oid, &sk.E )) ) - // return ec; - skey[1] = ec2os (q_x, q_y, sk.E.p); /* public key */ // "q", public key, the point + skey[0] = name_oid_to_mpi( sk.E.name_oid ); /* "c", name OID */ + /* if( (ec=fill_in_curve( sk.E.name_oid, &sk.E )) ) */ + /* return ec; */ + skey[1] = ec2os (q_x, q_y, sk.E.p); /* public key */ + /* "q", public key, the point */ mpi_free (q_x); mpi_free (q_y); - if( algo == GCRY_PK_ECDSA ) { - skey[2] = sk.d; - } - else { - skey[2] = (kek_params ? kek_params : mpi_new (0)); // params, the last field in the public key portion - skey[3] = sk.d; - } + if (algo == GCRY_PK_ECDSA) + { + skey[2] = sk.d; + } + else + { + /* PARAMS, the last field in the public key portion. */ + skey[2] = (kek_params ? kek_params : mpi_new (0)); + + skey[3] = sk.d; + } point_free (&sk.E.G); point_free (&sk.Q); @@ -1172,19 +1206,21 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, return gpg_err_code_from_syserror (); if (DBG_CIPHER) - { - if( algo == GCRY_PK_ECDSA ) { - log_mpidump ("ecgen DSA c ", skey[0]); - log_mpidump ("ecgen DSA Q ", skey[1]); - log_mpidump ("ecgen DSA d ", skey[2]); - } - else { - log_mpidump ("ecgen DH c ", skey[0]); - log_mpidump ("ecgen DH Q ", skey[1]); - log_mpidump ("ecgen DH p ", skey[2]); - log_mpidump ("ecgen DH d ", skey[3]); + { + if (algo == GCRY_PK_ECDSA) + { + log_mpidump ("ecgen DSA c ", skey[0]); + log_mpidump ("ecgen DSA Q ", skey[1]); + log_mpidump ("ecgen DSA d ", skey[2]); + } + else + { + log_mpidump ("ecgen DH c ", skey[0]); + log_mpidump ("ecgen DH Q ", skey[1]); + log_mpidump ("ecgen DH p ", skey[2]); + log_mpidump ("ecgen DH d ", skey[3]); + } } - } return 0; } @@ -1198,11 +1234,14 @@ ecc_generate (int algo, unsigned int nbits, unsigned long evalue, return ecc_generate_ext (algo, nbits, 0, NULL, skey, retfactors, NULL); } + #if 0 -/* Need to be implemented, if called neeeded. The issue is that the purpose of this function is to return the information about - * the curve that is beyond the information present in the public key. In particular, the pkey size is now just 2, - * while we may need to return E.a, E.b, E.p, E.n, E.g, type of the curve, at the minimum. - * This information is readily available for well-known named curves. +/* Need to be implemented, if called neeeded. The issue is that the + * purpose of this function is to return the information about the + * curve that is beyond the information present in the public key. In + * particular, the pkey size is now just 2, while we may need to + * return E.a, E.b, E.p, E.n, E.g, type of the curve, at the minimum. + * This information is readily available for well-known named curves. */ /* Return the parameters of the curve NAME. */ static gcry_err_code_t @@ -1213,7 +1252,7 @@ ecc_get_param (const char *name, gcry_mpi_t *pkey) elliptic_curve_t E; mpi_ec_t ctx; gcry_mpi_t g_x, g_y; - + err = generate_curve (0, name, &E, &nbits); if (err) return err; @@ -1315,6 +1354,7 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey) return err; } + static gcry_err_code_t ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, int (*cmp)(void *, gcry_mpi_t), void *opaquev) @@ -1348,17 +1388,19 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, } -/* ecdh raw is classic 2-round DH protocol published in 1976. - * Some overloading is needed to fit it to encrypt/decrypt PK interface of libgcrypt. - * - * The only need for this complexity is that some designs of client of libgcrypt - * don't allow to get the private components of public keys. +/* ecdh raw is classic 2-round DH protocol published in 1976. + * + * Some overloading is needed to fit it to encrypt/decrypt PK + * interface of libgcrypt. The only need for this complexity is that + * some designs of client of libgcrypt don't allow to get the private + * components of public keys. * * Overview of ecc_encrypt_raw and ecc_decrypt_raw. * - * As with any PK operation, encrypt version uses a public key and decrypt -- private. + * As with any PK operation, encrypt version uses a public key and + * decrypt -- private. * - * Symbols used bellow: + * Symbols used below: * G - field generator point * x - private long-term scalar * xG - public long-term key @@ -1369,18 +1411,21 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, * ecc_encrypt_raw description: * input: * data[0] : private scalar (k) - * output: - * resaddr[0] : shared point (k*x*G, where x is the secret scalar of pkey; it's the shared secret) + * output: + * resaddr[0] : shared point (k*x*G, where x is the secret scalar of pkey; + * it's the shared secret) * resaddr[1] : generated ephemeral public key (kG) * * ecc_decrypt_raw description: * input: * data[0] : a point kG (ephemeral public key) * output: - * result[0] : shared point (k*x*G, where x is the secret scalar of pkey; it's the shared secret) + * result[0] : shared point (k*x*G, where x is the secret scalar of pkey; + * it's the shared secret) */ static gcry_err_code_t -ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey, int flags) +ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, + gcry_mpi_t *pkey, int flags) { ECC_secret_key sk; mpi_ec_t ctx; @@ -1391,22 +1436,23 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey (void)flags; if (DBG_CIPHER) - log_debug ("Called ecc_encrypt_raw data size=%d bits, flags=%08x\n", gcry_mpi_get_nbits (data), flags); + log_debug ("Called ecc_encrypt_raw data size=%d bits, flags=%08x\n", + gcry_mpi_get_nbits (data), flags); if ( !data || !pkey[0] || !pkey[1] ) return GPG_ERR_BAD_MPI; if (DBG_CIPHER) - { - log_mpidump ("ecdh encrypt PK c ", pkey[0]); - log_mpidump ("ecdh encrypt PK q ", pkey[1]); - log_mpidump ("ecdh encrypt PK p ", pkey[2]); - log_mpidump ("ecdh encrypt data k", data); - } + { + log_mpidump ("ecdh encrypt PK c ", pkey[0]); + log_mpidump ("ecdh encrypt PK q ", pkey[1]); + log_mpidump ("ecdh encrypt PK p ", pkey[2]); + log_mpidump ("ecdh encrypt data k", data); + } - if( (err=mpi_to_name_oid( pkey[0], sk.E.name_oid )) ) + if ((err=mpi_to_name_oid( pkey[0], sk.E.name_oid ))) return err; - if( (err=fill_in_curve( sk.E.name_oid, &sk.E )) ) + if ((err=fill_in_curve( sk.E.name_oid, &sk.E ))) return err; point_init (&sk.Q); @@ -1420,58 +1466,58 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey ctx = _gcry_mpi_ec_init (sk.E.p, sk.E.a); - - /* the following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */ + /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */ { - mpi_point_t R; /* result that we return */ - gcry_mpi_t x,y; + mpi_point_t R; /* Result that we return. */ + gcry_mpi_t x, y; - x = mpi_new (0); - y = mpi_new (0); + x = mpi_new (0); + y = mpi_new (0); point_init (&R); _gcry_mpi_ec_mul_point (&R, sk.d, &sk.Q, ctx); if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) - log_fatal ("ecdh: Failed to get affine coordinates for xkG\n"); + log_fatal ("ecdh: Failed to get affine coordinates for xkG\n"); - result[0] = ec2os( x, y, sk.E.p ); /* xkG */ + result[0] = ec2os (x, y, sk.E.p); /* xkG */ _gcry_mpi_ec_mul_point (&R, sk.d, &sk.E.G, ctx); if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) - log_fatal ("ecdh: Failed to get affine coordinates for kG\n"); + log_fatal ("ecdh: Failed to get affine coordinates for kG\n"); - result[1] = ec2os( x, y, sk.E.p ); /* kG */ + result[1] = ec2os (x, y, sk.E.p); /* kG */ - mpi_free(x); - mpi_free(y); + mpi_free (x); + mpi_free (y); - point_free( &R ); + point_free (&R); } _gcry_mpi_ec_free (ctx); - ecc_sk_free( &sk ); + ecc_sk_free (&sk); - if( result[0] == NULL || result[1] == NULL ) { - mpi_free( result[0] ); - mpi_free( result[1] ); - return GPG_ERR_ENOMEM; - } + if (!result[0] || !result[1]) + { + mpi_free (result[0]); + mpi_free (result[1]); + return GPG_ERR_ENOMEM; + } - /* success */ + /* Success. */ - /* none of 2 returned values are used as is; they are further processed at OpenPGP layer. - * However, they match the number of MPIs (2) needed to encrypt a message in OpenPGP format - */ + /* None of 2 returned values are used as is; they are further + * processed at OpenPGP layer. However, they match the number of + * MPIs (2) needed to encrypt a message in OpenPGP format. */ resarr[0] = result[0]; - resarr[1] = result[1]; + resarr[1] = result[1]; - return GPG_ERR_NO_ERROR; + return 0; } - /* input: +/* input: * data[0] : a point kG (ephemeral public key) * output: * resaddr[0] : shared point k*x*G @@ -1479,10 +1525,11 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey * see ecc_encrypt_raw for details. */ static gcry_err_code_t -ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, gcry_mpi_t *skey, int flags) +ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, + gcry_mpi_t *skey, int flags) { ECC_secret_key sk; - mpi_point_t R; /* result that we return */ + mpi_point_t R; /* Result that we return. */ mpi_ec_t ctx; gcry_mpi_t r; int err; @@ -1493,30 +1540,31 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, gcry_mpi_t *ske *result = NULL; if (DBG_CIPHER) - log_debug ("Called ecc_encrypt_raw data size=%d bits, flags=%08x\n", gcry_mpi_get_nbits (data[0]), flags); + log_debug ("Called ecc_encrypt_raw data size=%d bits, flags=%08x\n", + gcry_mpi_get_nbits (data[0]), flags); - if ( !data || !data[0] || !skey[0] || !skey[1] || !skey[3] ) + if (!data || !data[0] || !skey[0] || !skey[1] || !skey[3]) return GPG_ERR_BAD_MPI; if (DBG_CIPHER) - { - log_mpidump ("ecdh decrypt SK c ", skey[0]); - log_mpidump ("ecdh decrypt SK q ", skey[1]); - log_mpidump ("ecdh decrypt SK p ", skey[2]); - log_mpidump ("ecdh decrypt data kG", data[0]); - } + { + log_mpidump ("ecdh decrypt SK c ", skey[0]); + log_mpidump ("ecdh decrypt SK q ", skey[1]); + log_mpidump ("ecdh decrypt SK p ", skey[2]); + log_mpidump ("ecdh decrypt data kG", data[0]); + } - if( (err=mpi_to_name_oid( skey[0], sk.E.name_oid )) ) + if ((err=mpi_to_name_oid( skey[0], sk.E.name_oid ))) return err; - if( (err=fill_in_curve( sk.E.name_oid, &sk.E )) ) + if ((err=fill_in_curve( sk.E.name_oid, &sk.E ))) return err; point_init (&sk.Q); err = os2ec (&sk.Q, data[0]); - sk.d = gcry_mpi_copy( skey[3] ); + sk.d = gcry_mpi_copy (skey[3]); if (err) { - ecc_sk_free( &sk ); + ecc_sk_free (&sk); return err; } @@ -1525,42 +1573,45 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, gcry_mpi_t *ske point_init (&R); _gcry_mpi_ec_mul_point (&R, sk.d, &sk.Q, ctx); - /* the following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */ + /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so: */ { - gcry_mpi_t x,y; - x = mpi_new (0); - y = mpi_new (0); + gcry_mpi_t x, y; + + x = mpi_new (0); + y = mpi_new (0); if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) - log_fatal ("ecdh: Failed to get affine coordinates\n"); + log_fatal ("ecdh: Failed to get affine coordinates\n"); - r = ec2os( x, y, sk.E.p ); - mpi_free(x); - mpi_free(y); + r = ec2os (x, y, sk.E.p); + mpi_free (x); + mpi_free (y); } - point_free( &R ); + point_free (&R); _gcry_mpi_ec_free (ctx); - ecc_sk_free( &sk ); + ecc_sk_free (&sk) ; - if( r == NULL ) - return GPG_ERR_ENOMEM; + if (!r) + return GPG_ERR_ENOMEM; - /* success */ + /* Success. */ *result = r; - return GPG_ERR_NO_ERROR; + return 0; } + static unsigned int ecc_get_nbits (int algo, gcry_mpi_t *pkey) { (void)algo; - /* derive it from public key point Q, which is 1 byte + x + y */ + /* Derive it from public key point Q, which is 1 byte + x + y . */ return (mpi_get_nbits (pkey[1]) / (8*2)) * 8; } + /* See rsa.c for a description of this function. */ static gpg_err_code_t compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) @@ -1575,7 +1626,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) /* Clear the values for easier error cleanup. */ for (idx=0; idx < sizeof(values)/sizeof(values[0]); idx++) values[idx] = NULL; - + /* Fill values with all available parameters. */ for (idx=0; idx < sizeof(values)/sizeof(values[0]); idx++) { @@ -1591,9 +1642,10 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) } } } - + #if 0 - /* Not used now: curve name (DER OID of the name, actually) is always hashed above */ + /* Not used now: curve name (DER OID of the name, actually) is + always hashed above. */ /* Check whether a curve parameter is available and use that to fill in missing values. */ l1 = gcry_sexp_find_token (keyparam, "curve", 5); @@ -1601,7 +1653,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) { char *curve; gcry_mpi_t tmpvalues[N_ECC_PUBKEY_COMPONENETS]; - + for (idx = 0; idx < sizeof(tmpvalues)/sizeof(tmpvalues[0]); idx++) tmpvalues[idx] = NULL; @@ -1637,14 +1689,14 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) } else _gcry_mpi_normalize (values[idx]); - + /* Hash them all. */ for (idx = 0; idx < sizeof(values)/sizeof(values[0]); idx++) { char buf[30]; unsigned char *rawmpi; unsigned int rawmpilen; - + rawmpi = _gcry_mpi_get_buffer (values[idx], &rawmpilen, NULL); if (!rawmpi) { @@ -1661,7 +1713,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) leave: for (idx = 0; idx < sizeof(values)/sizeof(values[0]); idx++) _gcry_mpi_release (values[idx]); - + return ec; #undef N_ECC_PUBKEY_COMPONENETS } @@ -1670,7 +1722,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) -/* +/* Self-test section. */ @@ -1680,7 +1732,7 @@ selftests_ecdsa (selftest_report_func_t report) { const char *what; const char *errtxt; - + what = "low-level"; errtxt = NULL; /*selftest ();*/ if (errtxt) @@ -1713,7 +1765,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report) default: ec = GPG_ERR_PUBKEY_ALGO; break; - + } return ec; } @@ -1725,7 +1777,7 @@ static const char *ecdsa_names[] = { "ecdsa", "ecdh", - "ecc", // only here, for the minimum number of public parameters (= 2) + "ecc", /* Only here, for the minimum number of public parameters (= 2) */ NULL, }; static const char *ecdh_names[] = @@ -1763,11 +1815,10 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdh = }; -pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = +pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = { run_selftests, ecc_generate_ext, compute_keygrip, - NULL // ecc_get_param + NULL /* ecc_get_param */ }; - diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 6f0609c..64ae1a0 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -1,6 +1,6 @@ /* pubkey.c - pubkey dispatcher * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005, - * 2007, 2008 Free Software Foundation, Inc. + * 2007, 2008, 2011 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -983,7 +983,7 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, gcry_module_t module; gcry_pk_spec_t *pubkey; pk_extra_spec_t *extraspec; -// int is_ecc; + /* FIXME: Why has this been removed? int is_ecc; * /* Check that the first element is valid. */ list = gcry_sexp_find_token (sexp, @@ -1010,8 +1010,8 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, itself. We need a function to test whether an algorithm given with a key is compatible with an application of the key (signing, encryption). For RSA this is easy, but ECC is the first - algorithm which has many flavours. */ -// is_ecc = ( !strcmp (name, "ecdsa") || !strcmp (name, "ecc") ); + algorithm which has many flavours. */ + /* is_ecc = ( !strcmp (name, "ecdsa") || !strcmp (name, "ecc") ); */ gcry_free (name); if (!module) @@ -1031,9 +1031,10 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, err = gpg_err_code_from_errno (errno); if (!err) { - // if (is_ecc) - // err = sexp_elements_extract_ecc (list, elems, array, extraspec); - // else + /* FIXME: Removing this ECC case changes the ABI; we can't do it. */ + /* if (is_ecc) */ + /* err = sexp_elements_extract_ecc (list, elems, array, extraspec); */ + /* else */ err = sexp_elements_extract (list, elems, array, pubkey->name); } commit 54f50ea4d1e5d0e94d8cc16ed777fca88b076ee4 Author: Werner Koch Date: Thu Jan 20 17:42:37 2011 +0100 Revert version number to 1.5.0. Update AUTHORS and NEWS. diff --git a/AUTHORS b/AUTHORS index 74df956..571dcb1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -88,9 +88,13 @@ werner.dittmann at t-online.de GNUPG David Shaw Assigns past and future changes. -dshaw at jabberwocky.com> +dshaw at jabberwocky.com (cipher/camellia-glue.c and related stuff) +LIBGCRYPT Andrey Jivsov 2010-12-09 +Assigns Past and Future Changes +openpgp at brainhub.org +(cipher/ecc.c and related files) More credits @@ -119,7 +123,7 @@ security corporation. See the file for details. Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2006, - 2007, 2008, 2009 Free Software Foundation, Inc. + 2007, 2008, 2009, 2011 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without diff --git a/NEWS b/NEWS index 0b1ecbc..0724009 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,8 @@ Noteworthy changes in version 1.5.x (unreleased) * Support for WindowsCE. + * Support ECDH. + * Interface changes relative to the 1.4.2 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GCRY_CIPHER_MODE_AESWRAP NEW. diff --git a/configure.ac b/configure.ac index b7fa853..c6bff37 100644 --- a/configure.ac +++ b/configure.ac @@ -26,7 +26,7 @@ min_automake_version="1.10" # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [1.6.0]) +m4_define([my_version], [1.5.0]) m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([printf "%d" $(svn info 2>/dev/null \ ----------------------------------------------------------------------- Summary of changes: AUTHORS | 8 +- NEWS | 2 + cipher/ecc.c | 441 +++++++++++++++++++++++++++++++------------------------ cipher/pubkey.c | 15 +- configure.ac | 2 +- 5 files changed, 263 insertions(+), 205 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Fri Jan 21 04:41:49 2011 From: cvs at cvs.gnupg.org (by Marcus Brinkmann) Date: Fri, 21 Jan 2011 04:41:49 +0100 Subject: [git] GPGME - branch, master, updated. gpgme-1.1.8-161-g1f0f033 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "GnuPG Made Easy". The branch, master has been updated via 1f0f033f552b5cd81f02e761a0e31eb9a2c89ab8 (commit) from 3a7058cade6caec7ec38ca4b2a8c1826e6df6bb1 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 1f0f033f552b5cd81f02e761a0e31eb9a2c89ab8 Author: Marcus Brinkmann Date: Fri Jan 21 04:21:30 2011 +0100 Fix gpgconf option change if not self-assigning. 2011-01-21 Marcus Brinkmann * engine-gpgconf.c (_gpgme_conf_opt_change): Fix the case that is not self-assignment. diff --git a/src/ChangeLog b/src/ChangeLog index f891d98..fdd3e49 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2011-01-21 Marcus Brinkmann + + * engine-gpgconf.c (_gpgme_conf_opt_change): Fix the case that is + not self-assignment. + 2010-12-08 Werner Koch * gpgme-tool.c (strcpy_escaped_plus): New. diff --git a/src/engine-gpgconf.c b/src/engine-gpgconf.c index d08ed03..6807dce 100644 --- a/src/engine-gpgconf.c +++ b/src/engine-gpgconf.c @@ -622,7 +622,7 @@ _gpgme_conf_opt_change (gpgme_conf_opt_t opt, int reset, gpgme_conf_arg_t arg) { if (opt->new_value) release_arg (opt->new_value, opt->alt_type); - opt->new_value = NULL; + opt->new_value = NULL; opt->change_value = 0; } else @@ -630,10 +630,8 @@ _gpgme_conf_opt_change (gpgme_conf_opt_t opt, int reset, gpgme_conf_arg_t arg) /* Support self-assignment, for example for adding an item to an existing list. */ if (opt->new_value && arg != opt->new_value) - { - release_arg (opt->new_value, opt->alt_type); - opt->new_value = arg; - } + release_arg (opt->new_value, opt->alt_type); + opt->new_value = arg; opt->change_value = 1; } return 0; ----------------------------------------------------------------------- Summary of changes: src/ChangeLog | 5 +++++ src/engine-gpgconf.c | 8 +++----- 2 files changed, 8 insertions(+), 5 deletions(-) hooks/post-receive -- GnuPG Made Easy http://git.gnupg.org From cvs at cvs.gnupg.org Fri Jan 21 12:26:41 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Fri, 21 Jan 2011 12:26:41 +0100 Subject: [git] GnuPG - branch, ECC-INTEGRATION-2-1, updated. gnupg-2.1.0beta1-38-g90b0ff2 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, ECC-INTEGRATION-2-1 has been updated via 90b0ff23b7e51332592668e4034967c1aac1c593 (commit) from a66772aa6309a0e632ff802fd6dcfb034b61c5cf (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 90b0ff23b7e51332592668e4034967c1aac1c593 Author: Werner Koch Date: Fri Jan 21 12:00:57 2011 +0100 Editorial changes and allow building with old libgcrypts. Changed order of some conditional to make to put the special case into the true branch. Indentation changes. Minor other changes to make the ECC code more similar to the rest of our code. It builds but many sefltests still fail. Need to fix that before using it with an ECDH enabled libgcrypt. [/] 2011-01-21 Werner Koch * configure.ac: Need Libgcrypt 1.4.6 due to AESWRAP. (HAVE_GCRY_PK_ECDH): Add new test. [agent/] 2011-01-21 Werner Koch * cvt-openpgp.c (GCRY_PK_ECDH) [!HAVE_GCRY_PK_ECDH]: New. [include/] 2011-01-21 Werner Koch * cipher.h (GCRY_PK_USAGE_CERT): Remove compatibility macros because we now require libgcrypt 1.4.6. (GCRY_PK_ECDH): Add replacement. diff --git a/ChangeLog b/ChangeLog index 656fe72..287e4d1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2011-01-21 Werner Koch + + * configure.ac: Need Libgcrypt 1.4.6 due to AESWRAP. + (HAVE_GCRY_PK_ECDH): Add new test. + 2011-01-03 Werner Koch * README.SVN: Rename to README.GIT. diff --git a/agent/ChangeLog b/agent/ChangeLog index ce1fdcc..6992827 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,3 +1,7 @@ +2011-01-21 Werner Koch + + * cvt-openpgp.c (GCRY_PK_ECDH) [!HAVE_GCRY_PK_ECDH]: New. + 2010-12-02 Werner Koch * gpg-agent.c (CHECK_OWN_SOCKET_INTERVAL) [W32CE]: Set to 60 diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c index 73c31f7..02c2bc8 100644 --- a/agent/cvt-openpgp.c +++ b/agent/cvt-openpgp.c @@ -28,6 +28,13 @@ #include "i18n.h" #include "cvt-openpgp.h" +/* Macros for compatibility with older libgcrypt versions. */ +#ifndef HAVE_GCRY_PK_ECDSA +# define GCRY_PK_ECDH 302 +#endif + + + /* Helper to pass data via the callback to do_unprotect. */ struct try_do_unprotect_arg_s @@ -100,8 +107,8 @@ 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. - pubkey_algo is a libgcrypt ID + parameters into our s-expression based format. Note that + PUBKEY_ALGO is a standard id and not an OpenPGP id. */ static gpg_error_t convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey) @@ -111,7 +118,8 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey) *r_key = NULL; - pubkey_algo = map_pk_openpgp_to_gcry( pubkey_algo ); + /* FIXME: This is not consistent with the above comment. */ + pubkey_algo = map_pk_openpgp_to_gcry (pubkey_algo); switch (pubkey_algo) { @@ -224,9 +232,9 @@ do_unprotect (const char *passphrase, *r_key = NULL; - /* Unfortunately, the OpenPGP PK algorithm numbers need to be re-mapped for Libgcrypt - */ - pubkey_algo = map_pk_openpgp_to_gcry( pubkey_algo ); + /* Unfortunately, the OpenPGP PK algorithm numbers need to be + re-mapped for Libgcrypt. */ + pubkey_algo = map_pk_openpgp_to_gcry (pubkey_algo); /* Count the actual number of MPIs is in the array and set the remainder to NULL for easier processing later on. */ @@ -655,7 +663,7 @@ convert_from_openpgp (ctrl_t ctrl, gcry_sexp_t s_pgp, string = gcry_sexp_nth_string (list, 1); if (!string) goto bad_seckey; - pubkey_algo = gcry_pk_map_name (string); /* ligcrypt IDs */ + pubkey_algo = gcry_pk_map_name (string); xfree (string); if (gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &npkey) @@ -1022,7 +1030,6 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, } algo = gcry_pk_map_name (name); - log_debug ( "convert to openpgp begin for algo=%s\n", name ); xfree (name); switch (algo) @@ -1052,7 +1059,6 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, err = apply_protection (array, npkey, nskey, passphrase, GCRY_CIPHER_AES, protect_iv, sizeof protect_iv, 3, GCRY_MD_SHA1, salt, s2k_count); - ///log_debug ( "convert to openpgp: after applying protection, err = %d\n", err ); /* Turn it into the transfer key S-expression. Note that we always return a protected key. */ if (!err) @@ -1082,8 +1088,6 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, put_membuf_str (&mbuf, ")\n"); put_membuf (&mbuf, "", 1); - ///log_debug ( "convert to openpgp: calling gcry_sexp_build\n" ); - tmpkey = NULL; { char *format = get_membuf (&mbuf, NULL); @@ -1093,7 +1097,6 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, err = gcry_sexp_build_array (&tmpkey, NULL, format, format_args); xfree (format); } - ///log_debug ( "convert to openpgp: calling gcry_sexp_build before err=%d\n", err ); if (!err) err = gcry_sexp_build (&tmpsexp, NULL, "(openpgp-private-key\n" @@ -1106,7 +1109,6 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, (int)sizeof protect_iv, protect_iv, (int)sizeof salt, salt, countbuf); - ///log_debug ( "convert to openpgp: after gcry_sexp_build, err = %d\n", err ); gcry_sexp_release (tmpkey); if (!err) err = make_canon_sexp_pad (tmpsexp, 0, r_transferkey, r_transferkeylen); @@ -1116,8 +1118,5 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, for (i=0; i < DIM (array); i++) gcry_mpi_release (array[i]); - log_debug ( "convert to openpgp end with err=%d\n", err ); - return err; } - diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index d85283a..db90392 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -2304,6 +2304,8 @@ check_for_running_agent (int silent, int mode) } /* TODO: it is also in misc, which is not linked with the agent */ +/* FIXME: The agent should not know about openpgp internals - weel + except for some stuff in cvt-openpgp. */ int map_pk_openpgp_to_gcry (int algo) { diff --git a/agent/protect.c b/agent/protect.c index d146653..d0a5fe9 100644 --- a/agent/protect.c +++ b/agent/protect.c @@ -43,7 +43,7 @@ /* A table containing the information needed to create a protected - private key */ + private key. */ static struct { const char *algo; const char *parmlist; @@ -428,9 +428,6 @@ agent_protect (const unsigned char *plainkey, const char *passphrase, unsigned char *p; gcry_md_hd_t md; - if (opt.debug & DBG_CRYPTO_VALUE) - log_info ("Protecting key=%s, passphrase=%s\n", plainkey, passphrase); - /* Create an S-expression with the protected-at timestamp. */ memcpy (timestamp_exp, "(12:protected-at15:", 19); gnupg_get_isotime (timestamp_exp+19); @@ -459,55 +456,41 @@ agent_protect (const unsigned char *plainkey, const char *passphrase, for (infidx=0; protect_info[infidx].algo && !smatch (&s, n, protect_info[infidx].algo); infidx++) ; - if (!protect_info[infidx].algo) { - log_info ("Unsupported alg %d for protection\n", protect_info[infidx].algo); + if (!protect_info[infidx].algo) return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); - } prot_begin = prot_end = NULL; for (i=0; (c=protect_info[infidx].parmlist[i]); i++) { if (i == protect_info[infidx].prot_from) prot_begin = s; - if (*s != '(') { - log_info ("Unbalanced bracket in S-expression #1\n"); + if (*s != '(') return gpg_error (GPG_ERR_INV_SEXP); - } depth++; s++; n = snext (&s); - if (!n) { - log_info ("Cannot get the length of S-expression field\n"); + if (!n) return gpg_error (GPG_ERR_INV_SEXP); - } - if (n != 1 || c != *s) { - log_info ("Invalid length in S-expression field\n"); + if (n != 1 || c != *s) return gpg_error (GPG_ERR_INV_SEXP); - } - s += n; + s += n; n = snext (&s); - if (!n) { - log_info ("Invalid fieled in S-expression field\n"); + if (!n) return gpg_error (GPG_ERR_INV_SEXP); - } s +=n; /* skip value */ - if (*s != ')') { - log_info ("Unbalanced bracket in S-expression #2\n"); + if (*s != ')') return gpg_error (GPG_ERR_INV_SEXP); - } depth--; if (i == protect_info[infidx].prot_to) prot_end = s; s++; } - if (*s != ')' || !prot_begin || !prot_end ) { - log_info ("Unbalanced bracket in S-expression #3\n"); + if (*s != ')' || !prot_begin || !prot_end ) return gpg_error (GPG_ERR_INV_SEXP); - } depth--; hash_end = s; s++; - /* skip to the end of the S-exp */ + /* Skip to the end of the S-expression. */ assert (depth == 1); rc = sskip (&s, &depth); if (rc) diff --git a/common/convert.c b/common/convert.c index 0a0c46f..5df6b33 100644 --- a/common/convert.c +++ b/common/convert.c @@ -23,7 +23,7 @@ #include #include "util.h" -#include "gcrypt.h" +#include "gcrypt.h" /* FIXME: really needed? */ #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A')) @@ -250,7 +250,10 @@ hex2str_alloc (const char *hexstring, size_t *r_count) * caller must free with xfree * Returns NULL on error, never throws */ -char *mpi2hex( gcry_mpi_t m ) { +char * +mpi2hex( gcry_mpi_t m ) +{ +#warning we have code for this in libcrypt size_t nbytes; size_t nbytes2; int rc; @@ -270,7 +273,9 @@ char *mpi2hex( gcry_mpi_t m ) { bin2hex( p+2*nbytes+1, nbytes2, p ); p[nbytes2*2] = '\0'; -//printf("%s:%d>>>> Created the string %s from %d bytes %02x %02x ..., MPI was %d bytes\n", __FILE__, __LINE__, p, nbytes2, p[2*nbytes+1], p[2*nbytes+2], nbytes); + /*printf("%s:%d>>>> Created the string %s from %d bytes %02x %02x + ..., MPI was %d bytes\n", __FILE__, __LINE__, p, nbytes2, + p[2*nbytes+1], p[2*nbytes+2], nbytes); */ return p; } diff --git a/configure.ac b/configure.ac index 575c1ec..ef6d2f9 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ min_automake_version="1.10" # Remember to change the version number immediately *after* a release. # Set my_issvn to "yes" for non-released code. Remember to run an # "svn up" and "autogen.sh" right before creating a distribution. -m4_define([my_version], [2.2.0]) +m4_define([my_version], [2.1.0]) m4_define([my_issvn], [yes]) m4_define([svn_revision], m4_esyscmd([printf "%d" $(svn info 2>/dev/null \ @@ -43,7 +43,7 @@ development_version=no NEED_GPG_ERROR_VERSION=1.8 NEED_LIBGCRYPT_API=1 -NEED_LIBGCRYPT_VERSION=1.6.0 +NEED_LIBGCRYPT_VERSION=1.4.6 NEED_LIBASSUAN_API=2 NEED_LIBASSUAN_VERSION=2.0.0 @@ -724,6 +724,20 @@ AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION", AM_PATH_LIBGCRYPT("$NEED_LIBGCRYPT_API:$NEED_LIBGCRYPT_VERSION", have_libgcrypt=yes,have_libgcrypt=no) +AC_CACHE_CHECK([whether Libgcrypt support ECDH], gnupg_cv_gcry_pk_ecdh, + [ _gnupg_gcry_save_cflags=$CFLAGS + CFLAGS="$CFLAGS $LIBGCRYPT_CFLAGS" + AC_TRY_COMPILE( + [#include ], + [ return GCRY_PK_ECDH; ], + gnupg_cv_gcry_pk_ecdh=yes, + gnupg_cv_gcry_pk_ecdh=no) + CFLAGS=$_gnupg_gcry_save_cflags]) +if test "$gnupg_cv_gcry_pk_ecdh" = yes; then + AC_DEFINE([HAVE_GCRY_PK_ECDH], 1, + [Define if gcrypt.h has the enum value for ECDH.]) +fi + # # libassuan is used for IPC diff --git a/dirmngr/Makefile.am b/dirmngr/Makefile.am index 0285fc8..128d7c3 100644 --- a/dirmngr/Makefile.am +++ b/dirmngr/Makefile.am @@ -61,7 +61,7 @@ endif dirmngr_LDADD = $(libcommonpth) ../gl/libgnu.a $(DNSLIBS) $(LIBASSUAN_LIBS) \ $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(PTH_LIBS) $(LIBINTL) $(LIBICONV) if !USE_LDAPWRAPPER -dirmngr_LDADD += $(LDAPLIBS) -llber +dirmngr_LDADD += $(LDAPLIBS) -llber #FIXME: Test for liblber first. endif dirmngr_LDFLAGS = $(extra_bin_ldflags) diff --git a/g10/armor.c b/g10/armor.c index 8cfd35c..a6195fc 100644 --- a/g10/armor.c +++ b/g10/armor.c @@ -1079,7 +1079,7 @@ armor_filter( void *opaque, int control, iobuf_writestr(a,afx->eol); if( !opt.no_version ) { - iobuf_writestr(a, "Version: GnuPG v" VERSION "-ecc (" + iobuf_writestr(a, "Version: GnuPG v" VERSION " (" PRINTABLE_OS_NAME ")" ); iobuf_writestr(a,afx->eol); } diff --git a/g10/build-packet.c b/g10/build-packet.c index 3a2c206..d138e06 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -178,21 +178,20 @@ mpi_write (iobuf_t out, gcry_mpi_t a) return rc; } -/* - * Write the name OID, encoded as an mpi, to OUT. The format of the content of the MPI is - * one byte LEN, following by LEN bytes that are DER representation of an ASN.1 OID. - * This is true for each of the 3 following functions. - */ +/* Write the name OID, encoded as an mpi, to OUT. The format of the + * content of the MPI is one byte LEN, following by LEN bytes that are + * DER representation of an ASN.1 OID. This is true for each of the 3 + * following functions. */ #define iobuf_name_oid_write iobuf_write_size_body_mpi + /* Write the value of KEK fields for ECDH. */ #define ecdh_kek_params_write iobuf_write_size_body_mpi -/* Write the value of encrypted filed for ECDH. */ + +/* Write the value of encrypted filed for ECDH. */ #define ecdh_esk_write iobuf_write_size_body_mpi -/**************** - * calculate the length of a packet described by PKT - */ +/* Calculate the length of a packet described by PKT. */ u32 calc_packet_length( PACKET *pkt ) { @@ -300,24 +299,35 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) } assert (npkey < nskey); - if( pk->pubkey_algo != PUBKEY_ALGO_ECDSA && pk->pubkey_algo != PUBKEY_ALGO_ECDH ) { - /* Writing the public parameters is easy, */ - for (i=0; i < npkey; i++ ) - if ((err = mpi_write (a, pk->pkey[i]))) - goto leave; - } - else { - /* ... except we do an adjustment for ECC OID and possibly KEK params for ECDH */ - if( (err=iobuf_name_oid_write(a, pk->pkey[0])) || /* DER of OID with preceeding length byte */ - (err = mpi_write (a, pk->pkey[1])) ) /* point Q, the public key */ + /* Writing the public parameters is easy. Except if we do an + adjustment for ECC OID and possibly KEK params for ECDH. */ + if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA + || pk->pubkey_algo == PUBKEY_ALGO_ECDH) { - goto leave; + /* Write DER of OID with preceeding length byte. */ + err = iobuf_name_oid_write (a, pk->pkey[0]); + if (err) + goto leave; + /* Write point Q, the public key. */ + err = mpi_write (a, pk->pkey[1]); + if (err) + goto leave; + + /* Write one more public field for ECDH. */ + if (pk->pubkey_algo == PUBKEY_ALGO_ECDH) + { + err = ecdh_kek_params_write(a,pk->pkey[2]); + if (err) + goto leave; + } } - if( pk->pubkey_algo == PUBKEY_ALGO_ECDH && (err=ecdh_kek_params_write(a,pk->pkey[2]))) { /* one more public field for ECDH */ - goto leave; + else + { + for (i=0; i < npkey; i++ ) + if ((err = mpi_write (a, pk->pkey[i]))) + goto leave; } - /* followed by possibly protected private scalar */ - } + if (pk->seckey_info) { @@ -483,22 +493,25 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) if ( !n ) write_fake_data( a, enc->data[0] ); - if( enc->pubkey_algo != PUBKEY_ALGO_ECDH ) { - for (i=0; i < n && !rc ; i++ ) - rc = mpi_write(a, enc->data[i] ); - } - else { - /* the second field persists as a LEN+field structure, even though it is - * stored for uniformity as an MPI internally */ - assert( n==2 ); - rc = mpi_write(a, enc->data[0] ); - if( !rc ) rc = ecdh_esk_write(a, enc->data[1] ); - } + if (enc->pubkey_algo == PUBKEY_ALGO_ECDH ) + { + /* The second field persists as a LEN+field structure, even + * though it is stored for uniformity as an MPI internally. */ + assert (n == 2); + rc = mpi_write (a, enc->data[0]); + if (!rc) + rc = ecdh_esk_write (a, enc->data[1]); + } + else + { + for (i=0; i < n && !rc ; i++ ) + rc = mpi_write(a, enc->data[i] ); + } if (!rc) { - write_header(out, ctb, iobuf_get_temp_length(a) ); - rc = iobuf_write_temp( out, a ); + write_header (out, ctb, iobuf_get_temp_length(a) ); + rc = iobuf_write_temp (out, a); } iobuf_close(a); return rc; diff --git a/g10/ecdh.c b/g10/ecdh.c index 091a28c..cb251fe 100644 --- a/g10/ecdh.c +++ b/g10/ecdh.c @@ -1,5 +1,5 @@ /* ecdh.c - ECDH public key operations used in public key glue code - * Copyright (C) 2000, 2003 Free Software Foundation, Inc. + * Copyright (C) 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -31,10 +31,12 @@ #include "options.h" gcry_mpi_t -pk_ecdh_default_params_to_mpi( int qbits ) { +pk_ecdh_default_params_to_mpi (int qbits) +{ gpg_error_t err; gcry_mpi_t result; - /* Defaults are the strongest possible choices. Performance is not an issue here, only interoperability. */ + /* Defaults are the strongest possible choices. Performance is not + an issue here, only interoperability. */ byte kek_params[4] = { 3 /*size of following field*/, 1 /*fixed version for KDF+AESWRAP*/, @@ -50,41 +52,49 @@ pk_ecdh_default_params_to_mpi( int qbits ) { } kek_params_table[] = { { 256, DIGEST_ALGO_SHA256, CIPHER_ALGO_AES }, { 384, DIGEST_ALGO_SHA384, CIPHER_ALGO_AES256 }, - { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 } // 528 is 521 rounded to the 8 bit boundary + + /* Note: 528 is 521 rounded to the 8 bit boundary */ + { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 } }; - for( i=0; i= qbits ) { - kek_params[2] = kek_params_table[i].openpgp_hash_id; - kek_params[3] = kek_params_table[i].openpgp_cipher_id; - break; + for (i=0; i= qbits) + { + kek_params[2] = kek_params_table[i].openpgp_hash_id; + kek_params[3] = kek_params_table[i].openpgp_cipher_id; + break; + } } - } - if( DBG_CIPHER ) - log_printhex ("ecdh kek params are", kek_params, sizeof(kek_params) ); + if (DBG_CIPHER) + log_printhex ("ecdh kek params are", kek_params, sizeof(kek_params) ); - err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, kek_params, sizeof(kek_params), NULL); + err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, + kek_params, sizeof(kek_params), NULL); if (err) log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); return result; } -/* returns allocated (binary) KEK parameters; the size is returned in sizeout. - * The caller must free returned value with xfree. - * Returns NULL on error + +/* Returns allocated (binary) KEK parameters; the size is returned in + * sizeout. The caller must free the returned value with xfree. + * Returns NULL on error. */ byte * -pk_ecdh_default_params( int qbits, size_t *sizeout ) { - /* Defaults are the strongest possible choices. Performance is not an issue here, only interoperability. */ +pk_ecdh_default_params (int qbits, size_t *sizeout) +{ + /* Defaults are the strongest possible choices. Performance is not + an issue here, only interoperability. */ byte kek_params[4] = { 3 /*size of following field*/, 1 /*fixed version for KDF+AESWRAP*/, DIGEST_ALGO_SHA512 /* KEK MD */, - CIPHER_ALGO_AES256 /*KEK AESWRAP alg*/ + CIPHER_ALGO_AES256 /* KEK AESWRAP alg */ }; int i; - + static const struct { int qbits; int openpgp_hash_id; @@ -92,39 +102,48 @@ pk_ecdh_default_params( int qbits, size_t *sizeout ) { } kek_params_table[] = { { 256, DIGEST_ALGO_SHA256, CIPHER_ALGO_AES }, { 384, DIGEST_ALGO_SHA384, CIPHER_ALGO_AES256 }, - { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 } // 528 is 521 rounded to the 8 bit boundary + /* Note: 528 is 521 rounded to the 8 bit boundary */ + { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 } }; byte *p; *sizeout = 0; - - for( i=0; i= qbits ) { - kek_params[2] = kek_params_table[i].openpgp_hash_id; - kek_params[3] = kek_params_table[i].openpgp_cipher_id; - break; + + for (i=0; i= qbits) + { + kek_params[2] = kek_params_table[i].openpgp_hash_id; + kek_params[3] = kek_params_table[i].openpgp_cipher_id; + break; + } } - } - if( DBG_CIPHER ) - log_printhex ("ecdh kek params are", kek_params, sizeof(kek_params) ); + if (DBG_CIPHER ) + log_printhex ("ecdh kek params are", kek_params, sizeof(kek_params)); - p = xtrymalloc( sizeof(kek_params) ); - if( p == NULL ) + p = xtrymalloc (sizeof(kek_params)); + if (!p) return NULL; - memcpy( p, kek_params, sizeof(kek_params) ); + memcpy (p, kek_params, sizeof(kek_params)); *sizeout = sizeof(kek_params); return p; } -/* Encrypts/decrypts 'data' with a key derived from shared_mpi ECC point using FIPS SP 800-56A compliant method, which is - * key derivation + key wrapping. The direction is determined by the first parameter (is_encrypt=1 --> this is encryption). - * The result is returned in out as a size+value MPI. + +/* Encrypts/decrypts 'data' with a key derived from shared_mpi ECC + * point using FIPS SP 800-56A compliant method, which is key + * derivation + key wrapping. The direction is determined by the first + * parameter (is_encrypt=1 --> this is encryption). The result is + * returned in out as a size+value MPI. + * * TODO: memory leaks (x_secret). */ static int -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 *out) +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 *out) { byte *secret_x; int secret_x_size; @@ -141,55 +160,70 @@ pk_ecdh_encrypt_with_shared_point ( int is_encrypt, gcry_mpi_t shared_mpi, { size_t nbytes; - /* extract x component of the shared point: this is the actual shared secret */ + /* Extract x component of the shared point: this is the actual + shared secret */ nbytes = (mpi_get_nbits (pkey[1] /* public point */)+7)/8; secret_x = xmalloc_secure( nbytes ); - rc = gcry_mpi_print (GCRYMPI_FMT_USG, secret_x, nbytes, &nbytes, shared_mpi); - if( rc ) { - xfree( secret_x ); - log_error ("ec ephemeral export of shared point failed: %s\n", gpg_strerror (rc) ); - return rc; - } + rc = gcry_mpi_print (GCRYMPI_FMT_USG, secret_x, nbytes, + &nbytes, shared_mpi); + if (rc) + { + xfree (secret_x); + log_error ("ec ephemeral export of shared point failed: %s\n", + gpg_strerror (rc)); + return rc; + } 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 ); + 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 ); + if (DBG_CIPHER) + log_printhex ("ecdh shared secret X is:", secret_x, secret_x_size ); } - /*** We have now the shared secret bytes in secret_x ***/ + /*** We have now the shared secret bytes in secret_x. ***/ - /* At this point we are done with PK encryption and the rest of the function uses symmetric - * key encryption techniques to protect the input 'data'. The following two sections will - * simply replace current secret_x with a value derived from it. This will become a KEK. + /* At this point we are done with PK encryption and the rest of the + * function uses symmetric key encryption techniques to protect the + * input 'data'. The following two sections will simply replace + * current secret_x with a value derived from it. This will become + * a KEK. */ { IOBUF obuf = iobuf_temp(); rc = iobuf_write_size_body_mpi ( obuf, pkey[2] ); /* KEK params */ + + kdf_params_size = iobuf_temp_to_buffer (obuf, + kdf_params, sizeof(kdf_params)); - kdf_params_size = iobuf_temp_to_buffer( obuf, kdf_params, sizeof(kdf_params) ); - - if( DBG_CIPHER ) - log_printhex ("ecdh KDF public key params are:", kdf_params, kdf_params_size ); + if (DBG_CIPHER) + log_printhex ("ecdh KDF public key params are:", + kdf_params, kdf_params_size ); - if( kdf_params_size != 4 || kdf_params[0] != 3 || kdf_params[1] != 1 ) /* expect 4 bytes 03 01 hash_alg symm_alg */ + /* Expect 4 bytes 03 01 hash_alg symm_alg. */ + if (kdf_params_size != 4 || kdf_params[0] != 3 || kdf_params[1] != 1) return GPG_ERR_BAD_PUBKEY; kdf_hash_algo = kdf_params[2]; kdf_encr_algo = kdf_params[3]; - if( DBG_CIPHER ) - log_debug ("ecdh KDF algorithms %s+%s with aeswrap\n", gcry_md_algo_name (kdf_hash_algo), openpgp_cipher_algo_name (kdf_encr_algo) ); + if (DBG_CIPHER) + log_debug ("ecdh KDF algorithms %s+%s with aeswrap\n", + gcry_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 ) + if (kdf_hash_algo != GCRY_MD_SHA256 + && kdf_hash_algo != GCRY_MD_SHA384 + && kdf_hash_algo != GCRY_MD_SHA512) return GPG_ERR_BAD_PUBKEY; - if( kdf_encr_algo != GCRY_CIPHER_AES128 && kdf_encr_algo != GCRY_CIPHER_AES192 && kdf_encr_algo != GCRY_CIPHER_AES256 ) + if (kdf_encr_algo != GCRY_CIPHER_AES128 + && kdf_encr_algo != GCRY_CIPHER_AES192 + && kdf_encr_algo != GCRY_CIPHER_AES256) return GPG_ERR_BAD_PUBKEY; } - /* build kdf_params */ + /* Build kdf_params. */ { IOBUF obuf; @@ -205,13 +239,15 @@ pk_ecdh_encrypt_with_shared_point ( int is_encrypt, gcry_mpi_t shared_mpi, /* fixed-length field 5, recipient fp */ iobuf_write (obuf, pk_fp, 20); - kdf_params_size = iobuf_temp_to_buffer( obuf, kdf_params, sizeof(kdf_params) ); - iobuf_close( obuf ); - if( rc ) { + kdf_params_size = iobuf_temp_to_buffer (obuf, + kdf_params, sizeof(kdf_params)); + iobuf_close (obuf); + if (rc) return rc; - } - if( DBG_CIPHER ) - log_printhex ("ecdh KDF message params are:", kdf_params, kdf_params_size ); + + if(DBG_CIPHER) + log_printhex ("ecdh KDF message params are:", + kdf_params, kdf_params_size ); } /* Derive a KEK (key wrapping key) using kdf_params and secret_x. */ @@ -231,7 +267,8 @@ pk_ecdh_encrypt_with_shared_point ( int is_encrypt, gcry_mpi_t shared_mpi, assert( gcry_md_get_algo_dlen (kdf_hash_algo) >= 32 ); - memcpy (secret_x, gcry_md_read (h, kdf_hash_algo), gcry_md_get_algo_dlen (kdf_hash_algo)); + memcpy (secret_x, gcry_md_read (h, kdf_hash_algo), + gcry_md_get_algo_dlen (kdf_hash_algo)); gcry_md_close (h); old_size = secret_x_size; @@ -239,12 +276,13 @@ pk_ecdh_encrypt_with_shared_point ( int is_encrypt, gcry_mpi_t shared_mpi, secret_x_size = gcry_cipher_get_algo_keylen( kdf_encr_algo ); assert( secret_x_size <= gcry_md_get_algo_dlen (kdf_hash_algo) ); - memset( secret_x+secret_x_size, old_size-secret_x_size, 0 ); /* we could have allocated more, so clean the tail before returning */ - if( DBG_CIPHER ) + /* We could have allocated more, so clean the tail before returning. */ + memset( secret_x+secret_x_size, old_size-secret_x_size, 0 ); + if (DBG_CIPHER) log_printhex ("ecdh KEK is:", secret_x, secret_x_size ); - } - - /* And, finally, aeswrap with key secret_x */ + } + + /* And, finally, aeswrap with key secret_x. */ { gcry_cipher_hd_t hd; size_t nbytes; @@ -256,115 +294,134 @@ pk_ecdh_encrypt_with_shared_point ( int is_encrypt, gcry_mpi_t shared_mpi, rc = gcry_cipher_open (&hd, kdf_encr_algo, GCRY_CIPHER_MODE_AESWRAP, 0); if (rc) - { - log_error( "ecdh failed to initialize AESWRAP: %s\n", gpg_strerror (rc)); - return rc; - } + { + log_error ("ecdh failed to initialize AESWRAP: %s\n", + gpg_strerror (rc)); + return rc; + } rc = gcry_cipher_setkey (hd, secret_x, secret_x_size); xfree( secret_x ); if (rc) - { - gcry_cipher_close (hd); - log_error("ecdh failed in gcry_cipher_setkey: %s\n", gpg_strerror (rc)); - return rc; - } - - data_buf_size = (gcry_mpi_get_nbits(data)+7)/8; - assert( (data_buf_size & 7) == (is_encrypt ? 0 : 1) ); - - data_buf = xmalloc_secure( 1 + 2*data_buf_size + 8 ); - if( !data_buf ) { - gcry_cipher_close (hd); - return GPG_ERR_ENOMEM; - } - - 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 */ - rc = gcry_mpi_print (GCRYMPI_FMT_USG, in, data_buf_size, &nbytes, data/*in*/); - if( rc ) { - log_error("ecdh failed to export DEK: %s\n", gpg_strerror (rc)); + { gcry_cipher_close (hd); - xfree( data_buf ); + log_error ("ecdh failed in gcry_cipher_setkey: %s\n", + gpg_strerror (rc)); return rc; } - if( DBG_CIPHER ) - log_printhex ("ecdh encrypting :", in, data_buf_size ); + data_buf_size = (gcry_mpi_get_nbits(data)+7)/8; + assert ((data_buf_size & 7) == (is_encrypt ? 0 : 1)); - rc = gcry_cipher_encrypt (hd, data_buf+1, data_buf_size+8, in, data_buf_size); - memset( in, 0, data_buf_size); - gcry_cipher_close (hd); - if(rc) + data_buf = xtrymalloc_secure( 1 + 2*data_buf_size + 8); + if (!data_buf) { - log_error("ecdh failed in gcry_cipher_encrypt: %s\n", gpg_strerror (rc)); - xfree( data_buf ); - return rc; + gcry_cipher_close (hd); + return GPG_ERR_ENOMEM; } - data_buf[0] = data_buf_size+8; - - if( DBG_CIPHER ) - log_printhex ("ecdh encrypted to:", data_buf+1, data_buf[0] ); - rc = gcry_mpi_scan ( &result, GCRYMPI_FMT_USG, data_buf, 1+data_buf[0], NULL); /* (byte)size + aeswrap of DEK */ - xfree( data_buf ); - if(rc) + if (is_encrypt) { - log_error("ecdh failed to create an MPI: %s\n", gpg_strerror (rc)); - return rc; - } - - *out = result; - } - else { - byte *in; + byte *in = data_buf+1+data_buf_size+8; + + /* Write data MPI into the end of data_buf. data_buf is size + aeswrap data. */ + rc = gcry_mpi_print (GCRYMPI_FMT_USG, in, + data_buf_size, &nbytes, data/*in*/); + if (rc) + { + log_error ("ecdh failed to export DEK: %s\n", gpg_strerror (rc)); + gcry_cipher_close (hd); + xfree (data_buf); + return rc; + } + + if (DBG_CIPHER) + log_printhex ("ecdh encrypting :", in, data_buf_size ); + + rc = gcry_cipher_encrypt (hd, data_buf+1, data_buf_size+8, + in, data_buf_size); + memset (in, 0, data_buf_size); + gcry_cipher_close (hd); + if (rc) + { + log_error ("ecdh failed in gcry_cipher_encrypt: %s\n", + gpg_strerror (rc)); + xfree (data_buf); + return rc; + } + data_buf[0] = data_buf_size+8; + + if (DBG_CIPHER) + log_printhex ("ecdh encrypted to:", data_buf+1, data_buf[0] ); - rc = gcry_mpi_print (GCRYMPI_FMT_USG, data_buf, data_buf_size, &nbytes, data/*in*/); - if( nbytes != data_buf_size || data_buf[0] != data_buf_size-1 ) { - log_error("ecdh inconsistent size\n"); + rc = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, + data_buf, 1+data_buf[0], NULL); + /* (byte)size + aeswrap of DEK */ xfree( data_buf ); - return GPG_ERR_BAD_MPI; + if (rc) + { + log_error ("ecdh failed to create an MPI: %s\n", gpg_strerror (rc)); + return rc; + } + + *out = result; } + else + { + byte *in; + + rc = gcry_mpi_print (GCRYMPI_FMT_USG, data_buf, data_buf_size, + &nbytes, data/*in*/); + if (nbytes != data_buf_size || data_buf[0] != data_buf_size-1) + { + log_error ("ecdh inconsistent size\n"); + xfree (data_buf); + return GPG_ERR_BAD_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 ); - rc = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1, data_buf_size ); + if (DBG_CIPHER) + log_printhex ("ecdh decrypting :", data_buf+1, data_buf_size); + + rc = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1, + data_buf_size); gcry_cipher_close (hd); - if(rc) - { - log_error("ecdh failed in gcry_cipher_decrypt: %s\n", gpg_strerror (rc)); - xfree( data_buf ); - return rc; - } - - 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 ) { - // log_error("ecdh failed at decryption: invalid padding. %02x > 8\n", in[data_buf_size-1] ); - // return GPG_ERR_BAD_KEY; - //} + if (rc) + { + log_error ("ecdh failed in gcry_cipher_decrypt: %s\n", + gpg_strerror (rc)); + xfree (data_buf); + return rc; + } + + 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 ) */ + /* { */ + /* log_error("ecdh failed at decryption: invalid padding. %02x > 8\n", */ + /* in[data_buf_size-1] ); */ + /* return GPG_ERR_BAD_KEY; */ + /* } */ rc = gcry_mpi_scan ( &result, GCRYMPI_FMT_USG, in, data_buf_size, NULL); - xfree( data_buf ); - if(rc) - { - log_error("ecdh failed to create a plain text MPI: %s\n", gpg_strerror (rc)); - return rc; - } - + xfree (data_buf); + if (rc) + { + log_error ("ecdh failed to create a plain text MPI: %s\n", + gpg_strerror (rc)); + return rc; + } + *out = result; - } + } } - + return rc; } @@ -380,21 +437,22 @@ gen_k (unsigned nbits) gcry_mpi_randomize (k, nbits-1, GCRY_STRONG_RANDOM); - if( DBG_CIPHER ) { - unsigned char *buffer; - if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, k)) - BUG (); - log_debug("ephemeral scalar MPI #0: %s\n", buffer); - gcry_free( buffer ); - } + if (DBG_CIPHER) + { + unsigned char *buffer; + if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, k)) + BUG (); + log_debug("ephemeral scalar MPI #0: %s\n", buffer); + gcry_free( buffer ); + } return k; } -/* Perform ECDH encryption, which involves ECDH key generation. - */ +/* Perform ECDH encryption, which involves ECDH key generation. */ int -pk_ecdh_encrypt (gcry_mpi_t * resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t * pkey) +pk_ecdh_encrypt (gcry_mpi_t *resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], + gcry_mpi_t data, gcry_mpi_t * pkey) { gcry_sexp_t s_ciph, s_data, s_pkey; @@ -402,9 +460,9 @@ pk_ecdh_encrypt (gcry_mpi_t * resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcr int rc; gcry_mpi_t k; - nbits = pubkey_nbits( PUBKEY_ALGO_ECDH, pkey ); + nbits = pubkey_nbits (PUBKEY_ALGO_ECDH, pkey); - /*** Generate an ephemeral key, actually, a scalar ***/ + /*** Generate an ephemeral key, actually, a scalar. ***/ k = gen_k (nbits); if( k == NULL ) @@ -414,50 +472,63 @@ pk_ecdh_encrypt (gcry_mpi_t * resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcr * Now use ephemeral secret to get the shared secret. ***/ rc = gcry_sexp_build (&s_pkey, NULL, - "(public-key(ecdh(c%m)(q%m)(p%m)))", pkey[0], pkey[1], pkey[2]); + "(public-key(ecdh(c%m)(q%m)(p%m)))", + pkey[0], pkey[1], pkey[2]); if (rc) BUG (); - /* put the data into a simple list */ - if (gcry_sexp_build (&s_data, NULL, "%m", k)) /* ephemeral scalar goes as data */ + /* Put the data into a simple list. */ + /* Ephemeral scalar goes as data. */ + if (gcry_sexp_build (&s_data, NULL, "%m", k)) BUG (); - /* pass it to libgcrypt */ + /* Pass it to libgcrypt. */ rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey); gcry_sexp_release (s_data); gcry_sexp_release (s_pkey); if (rc) return rc; - /* finally, perform encryption */ + /* Finally, perform encryption. */ { - gcry_mpi_t shared = mpi_from_sexp (s_ciph, "a"); /* ... and get the shared point */ + /* ... and get the shared point/ */ + gcry_mpi_t shared; + + shared = mpi_from_sexp (s_ciph, "a"); gcry_sexp_release (s_ciph); - resarr[0] = mpi_from_sexp (s_ciph, "b"); /* ephemeral public key */ + /* Ephemeral public key. */ + resarr[0] = mpi_from_sexp (s_ciph, "b"); - if( DBG_CIPHER ) { + if (DBG_CIPHER) + { unsigned char *buffer; + if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, resarr[0])) BUG (); log_debug("ephemeral key MPI: %s\n", buffer); gcry_free( buffer ); - } - - rc = pk_ecdh_encrypt_with_shared_point ( 1 /*=encrypton*/, shared, pk_fp, data, pkey, resarr+1 ); - mpi_release( shared ); + } + + rc = pk_ecdh_encrypt_with_shared_point (1 /*=encrypton*/, shared, + pk_fp, data, pkey, resarr+1); + mpi_release (shared); } - + return rc; } -/* Perform ECDH decryption. - */ + +/* Perform ECDH decryption. */ int -pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t shared, gcry_mpi_t * skey) { +pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN], + gcry_mpi_t data, gcry_mpi_t shared, gcry_mpi_t * skey) +{ if (!data) return gpg_error (GPG_ERR_BAD_MPI); - return pk_ecdh_encrypt_with_shared_point ( 0 /*=decryption*/, shared, sk_fp, data/*encr data as an MPI*/, skey, result ); + return pk_ecdh_encrypt_with_shared_point (0 /*=decryption*/, shared, + sk_fp, data/*encr data as an MPI*/, + skey, result); } diff --git a/g10/encrypt.c b/g10/encrypt.c index 3c16309..f529215 100644 --- a/g10/encrypt.c +++ b/g10/encrypt.c @@ -894,8 +894,8 @@ write_pubkey_enc_from_list (PK_LIST pk_list, DEK *dek, iobuf_t out) compliance_failure(); } - fingerprint_from_pk( pk, fp, &fpn ); - assert( fpn == 20 ); + fingerprint_from_pk (pk, fp, &fpn); + assert (fpn == 20); /* Okay, what's going on: We have the session key somewhere in * the structure DEK and want to encode this session key in an diff --git a/g10/export.c b/g10/export.c index 82d9751..74a7b0c 100644 --- a/g10/export.c +++ b/g10/export.c @@ -1161,18 +1161,16 @@ build_sexp_seckey (iobuf_t out, PACKET *pkt, int *indent) /* iobuf_put (out,')'); iobuf_put (out,'\n'); */ /* (*indent)--; */ /* } */ -/* - else if (sk->pubkey_algo == PUBKEY_ALGO_ECDSA && !sk->is_protected) - { - write_sexp_line (out, indent, "(ecdsa\n"); - (*indent)++; - write_sexp_keyparm (out, indent, "c", sk->skey[0]); iobuf_put (out,'\n'); - write_sexp_keyparm (out, indent, "q", sk->skey[6]); iobuf_put (out,'\n'); - write_sexp_keyparm (out, indent, "d", sk->skey[7]); - iobuf_put (out,')'); iobuf_put (out,'\n'); - (*indent)--; - } -*/ + /* else if (sk->pubkey_algo == PUBKEY_ALGO_ECDSA && !sk->is_protected) */ + /* { */ + /* write_sexp_line (out, indent, "(ecdsa\n"); */ + /* (*indent)++; */ + /* write_sexp_keyparm (out, indent, "c", sk->skey[0]); iobuf_put (out,'\n'); */ + /* write_sexp_keyparm (out, indent, "q", sk->skey[6]); iobuf_put (out,'\n'); */ + /* write_sexp_keyparm (out, indent, "d", sk->skey[7]); */ + /* 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"); */ diff --git a/g10/gpg.c b/g10/gpg.c index 23b1934..3794aa2 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -813,7 +813,7 @@ my_strusage( int level ) const char *p; switch( level ) { - case 11: p = "gpg (GnuPG) ecc"; + case 11: p = "gpg (GnuPG)"; break; case 13: p = VERSION; break; case 17: p = PRINTABLE_OS_NAME; break; diff --git a/g10/keygen.c b/g10/keygen.c index f7f1526..e75da79 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -18,6 +18,7 @@ * along with this program; if not, see . */ +#warning wk: check these changes. #include #include #include @@ -43,7 +44,6 @@ #include "keyserver-internal.h" #include "call-agent.h" #include "pkglue.h" -#include "gcrypt.h" /* The default algorithms. If you change them remember to change them also in gpg.c:gpgconf_list. You should also check that the value diff --git a/g10/keyid.c b/g10/keyid.c index 2a9bd19..0405b8b 100644 --- a/g10/keyid.c +++ b/g10/keyid.c @@ -54,11 +54,11 @@ pubkey_letter( int 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_E: return 'g' ; case PUBKEY_ALGO_ELGAMAL: return 'G' ; case PUBKEY_ALGO_DSA: return 'D' ; - case PUBKEY_ALGO_ECDSA: return 'E' ; // ECC DSA (sign only) - case PUBKEY_ALGO_ECDH: return 'e' ; // ECC DH (encrypt only) + case PUBKEY_ALGO_ECDSA: return 'E' ; /* ECC DSA (sign only) */ + case PUBKEY_ALGO_ECDH: return 'e' ; /* ECC DH (encrypt only) */ default: return '?'; } } @@ -76,8 +76,6 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) unsigned int nbits; size_t nbytes; int npkey = pubkey_get_npkey (pk->pubkey_algo); - /* name OID, MPI of public point, [for ECDH only: KEK params] */ - enum gcry_mpi_format ecc_pub_format[3] = {GCRYMPI_FMT_USG, GCRYMPI_FMT_PGP, GCRYMPI_FMT_USG}; /* Two extra bytes for the expiration date in v3 */ if(pk->version<4) @@ -92,11 +90,17 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) } else { - for(i=0; i < npkey; i++ ) + for (i=0; i < npkey; i++ ) { - const enum gcry_mpi_format fmt = - ((pk->pubkey_algo==PUBKEY_ALGO_ECDSA || pk->pubkey_algo==PUBKEY_ALGO_ECDH) ? ecc_pub_format[i] : GCRYMPI_FMT_PGP); - + 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. */ + else + fmt = GCRYMPI_FMT_PGP; + if (gcry_mpi_print (fmt, NULL, 0, &nbytes, pk->pkey[i])) BUG (); pp[i] = xmalloc (nbytes); @@ -106,7 +110,7 @@ hash_public_key (gcry_md_hd_t md, PKT_public_key *pk) 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 */ @@ -724,13 +728,12 @@ keygrip_from_pk (PKT_public_key *pk, unsigned char *array) "(public-key(ecc(c%m)(q%m)))", pk->pkey[0], pk->pkey[1]); break; -/* - case PUBKEY_ALGO_ECDH: - err = gcry_sexp_build (&s_pkey, NULL, - "(public-key(ecdh(c%m)(q%m)(p%m)))", - pk->pkey[0], pk->pkey[1], pk->pkey[2]); - break; -*/ + + /* case PUBKEY_ALGO_ECDH: */ + /* err = gcry_sexp_build (&s_pkey, NULL, */ + /* "(public-key(ecdh(c%m)(q%m)(p%m)))", */ + /* pk->pkey[0], pk->pkey[1], pk->pkey[2]); */ + /* break; */ default: err = gpg_error (GPG_ERR_PUBKEY_ALGO); diff --git a/g10/main.h b/g10/main.h index e336e5c..c7980ac 100644 --- a/g10/main.h +++ b/g10/main.h @@ -87,9 +87,12 @@ u16 checksum_mpi( gcry_mpi_t a ); u32 buffer_to_u32( const byte *buffer ); const byte *get_session_marker( size_t *rlen ); int map_cipher_openpgp_to_gcry (int algo); -#define openpgp_cipher_open(_a,_b,_c,_d) gcry_cipher_open((_a),map_cipher_openpgp_to_gcry((_b)),(_c),(_d)) -#define openpgp_cipher_get_algo_keylen(_a) gcry_cipher_get_algo_keylen(map_cipher_openpgp_to_gcry((_a))) -#define openpgp_cipher_get_algo_blklen(_a) gcry_cipher_get_algo_blklen(map_cipher_openpgp_to_gcry((_a))) +#define openpgp_cipher_open(_a,_b,_c,_d) \ + gcry_cipher_open((_a),map_cipher_openpgp_to_gcry((_b)),(_c),(_d)) +#define openpgp_cipher_get_algo_keylen(_a) \ + gcry_cipher_get_algo_keylen(map_cipher_openpgp_to_gcry((_a))) +#define openpgp_cipher_get_algo_blklen(_a) \ + gcry_cipher_get_algo_blklen(map_cipher_openpgp_to_gcry((_a))) int openpgp_cipher_blocklen (int algo); int openpgp_cipher_test_algo( int algo ); const char *openpgp_cipher_algo_name (int algo); @@ -159,7 +162,8 @@ int pubkey_get_nenc( int algo ); unsigned int pubkey_nbits( int algo, gcry_mpi_t *pkey ); int mpi_print (estream_t stream, gcry_mpi_t a, int mode); int iobuf_write_size_body_mpi (iobuf_t out, gcry_mpi_t a); -int iobuf_read_size_body(iobuf_t inp, byte *body, int body_max_size, int pktlen, gcry_mpi_t *out); +int iobuf_read_size_body (iobuf_t inp, byte *body, int body_max_size, + int pktlen, gcry_mpi_t *out); int ecdsa_qbits_from_Q( int qbits ); @@ -258,7 +262,9 @@ int save_unprotected_key_to_card (PKT_public_key *sk, int keyno); #define KEYGEN_FLAG_NO_PROTECTION 1 #define KEYGEN_FLAG_TRANSIENT_KEY 2 -int pk_ecc_keypair_gen( PKT_public_key **pk_out, int algo, int keygen_flags, char **cache_nonce_addr, unsigned nbits); +int pk_ecc_keypair_gen (PKT_public_key **pk_out, int algo, + int keygen_flags, char **cache_nonce_addr, + unsigned nbits); /*-- openfile.c --*/ int overwrite_filep( const char *fname ); diff --git a/g10/misc.c b/g10/misc.c index a09636b..6f77119 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -1,6 +1,6 @@ /* misc.c - miscellaneous functions * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - * 2008, 2009 Free Software Foundation, Inc. + * 2008, 2009, 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -366,10 +366,17 @@ map_cipher_gcry_to_openpgp (int algo) } } +/* Map OpenPGP public key algorithm numbers to those used by + Libgcrypt. */ int map_pk_openpgp_to_gcry (int algo) { - return (algo==PUBKEY_ALGO_ECDSA ? GCRY_PK_ECDSA : (algo==PUBKEY_ALGO_ECDH ? GCRY_PK_ECDH : algo)); + switch (algo) + { + case PUBKEY_ALGO_ECDSA: return GCRY_PK_ECDSA; + case PUBKEY_ALGO_ECDH: return GCRY_PK_ECDH; + default: return algo; + } } @@ -416,13 +423,7 @@ openpgp_cipher_test_algo( int algo ) const char * openpgp_cipher_algo_name (int algo) { - return gcry_cipher_algo_name (map_cipher_openpgp_to_gcry (algo)); -} - -const char * -openpgp_pk_algo_name (int algo) -{ - return gcry_pk_algo_name ( algo == PUBKEY_ALGO_ECDSA ? GCRY_PK_ECDSA : ( algo == PUBKEY_ALGO_ECDH ? GCRY_PK_ECDH : algo ) ); + return gnupg_cipher_algo_name (map_cipher_openpgp_to_gcry (algo)); } int @@ -438,12 +439,7 @@ openpgp_pk_test_algo( int algo ) if (algo < 0 || algo > 110) return gpg_error (GPG_ERR_PUBKEY_ALGO); - if( algo == PUBKEY_ALGO_ECDSA ) - algo = GCRY_PK_ECDSA; - else if( algo == PUBKEY_ALGO_ECDH ) - algo = GCRY_PK_ECDH; - - return gcry_pk_test_algo ( algo ); + return gcry_pk_test_algo (map_pk_openpgp_to_gcry (algo)); } int @@ -461,12 +457,8 @@ openpgp_pk_test_algo2( int algo, unsigned int use ) if (algo < 0 || algo > 110) return gpg_error (GPG_ERR_PUBKEY_ALGO); - if( algo == PUBKEY_ALGO_ECDSA ) - algo = GCRY_PK_ECDSA; - else if( algo == PUBKEY_ALGO_ECDH ) - algo = GCRY_PK_ECDH; - - return gcry_pk_algo_info ( algo, GCRYCTL_TEST_ALGO, NULL, &use_buf); + return gcry_pk_algo_info (map_pk_openpgp_to_gcry (algo), + GCRYCTL_TEST_ALGO, NULL, &use_buf); } int @@ -507,10 +499,12 @@ openpgp_pk_algo_usage ( int algo ) /* Map the OpenPGP pubkey algorithm whose ID is contained in ALGO to a string representation of the algorithm name. For unknown algorithm - IDs this function returns "?". + IDs this function returns "?". */ const char * openpgp_pk_algo_name (int algo) { + /* We use fixed strings to have pretty names instead of those from + libgcrypt. */ switch (algo) { case PUBKEY_ALGO_RSA: @@ -522,10 +516,13 @@ openpgp_pk_algo_name (int algo) case PUBKEY_ALGO_DSA: return "dsa"; - default: return "?"; + case PUBKEY_ALGO_ECDSA:return "ecdsa"; + + case PUBKEY_ALGO_ECDH: return "ecdh"; + + default: gcry_pk_algo_name (map_pk_openpgp_to_gcry (algo)); } } -*/ int @@ -1444,6 +1441,7 @@ pubkey_nbits( int algo, gcry_mpi_t *key ) int rc, nbits; gcry_sexp_t sexp; +#warning Why this assert assert( algo != GCRY_PK_ECDSA && algo != GCRY_PK_ECDH ); if( algo == GCRY_PK_DSA ) { @@ -1506,10 +1504,12 @@ mpi_print (estream_t fp, gcry_mpi_t a, int mode) return n; } + /* - * Write a special size+body mpi a, to OUT. The format of the content of the MPI is - * one byte LEN, following by LEN bytes + * Write a special size+body mpi A, to OUT. The format of the content + * of the MPI is one byte LEN, following by LEN bytes. */ +/* FIXME: Rename this function: it is not in iobuf.c */ int iobuf_write_size_body_mpi (iobuf_t out, gcry_mpi_t a) { @@ -1538,57 +1538,68 @@ iobuf_write_size_body_mpi (iobuf_t out, gcry_mpi_t a) return iobuf_write( out, buffer, nbytes ); } + /* - * Read a special size+body from inp into body[body_max_size] and return it in a buffer and as MPI. - * On success the number of consumed bytes will body[0]+1. - * The format of the content of the returned MPI is one byte LEN, following by LEN bytes. - * Caller is expected to pre-allocate fixed-size 255 byte buffer (or smaller when appropriate). + * Read a special size+body from inp into body[body_max_size] and + * return it in a buffer and as MPI. On success the number of + * consumed bytes will body[0]+1. The format of the content of the + * returned MPI is one byte LEN, following by LEN bytes. Caller is + * expected to pre-allocate fixed-size 255 byte buffer (or smaller + * when appropriate). */ +/* FIXME: Rename this function: it is not in iobuf.c */ int -iobuf_read_size_body( iobuf_t inp, byte *body, int body_max_size, int pktlen, gcry_mpi_t *out ) { +iobuf_read_size_body (iobuf_t inp, byte *body, int body_max_size, + int pktlen, gcry_mpi_t *out ) +{ unsigned n; int rc; gcry_mpi_t result; *out = NULL; - if( (n = iobuf_readbyte(inp)) == -1 ) { - return G10ERR_INVALID_PACKET; - } - if( n >= body_max_size || n < 2) { - log_error("invalid size+body field\n"); - return G10ERR_INVALID_PACKET; - } + if( (n = iobuf_readbyte(inp)) == -1 ) + { + return G10ERR_INVALID_PACKET; + } + if ( n >= body_max_size || n < 2) + { + log_error("invalid size+body field\n"); + return G10ERR_INVALID_PACKET; + } body[0] = n; - if( (n = iobuf_read(inp, body+1, n)) == -1 ) { - log_error("invalid size+body field\n"); - return G10ERR_INVALID_PACKET; - } - if( n+1 > pktlen ) { - log_error("size+body field is larger than the packet\n"); - return G10ERR_INVALID_PACKET; - } + if ((n = iobuf_read(inp, body+1, n)) == -1) + { + log_error("invalid size+body field\n"); + return G10ERR_INVALID_PACKET; + } + if (n+1 > pktlen) + { + log_error("size+body field is larger than the packet\n"); + return G10ERR_INVALID_PACKET; + } rc = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, body, n+1, NULL); if (rc) log_fatal ("mpi_scan failed: %s\n", gpg_strerror (rc)); - + *out = result; - + return rc; } -/* pkey[1] or skey[1] is Q for ECDSA, which is an uncompressed point, i.e. 04 */ -int ecdsa_qbits_from_Q( int qbits ) { - if( qbits%8>3 ) { - log_error(_("ECDSA public key is expected to be in SEC encoding multiple of 8 bits\n")); - return 0; - } - qbits -= qbits%8; - qbits /= 2; - return qbits; +/* pkey[1] or skey[1] is Q for ECDSA, which is an uncompressed point, + i.e. 04 */ +int +ecdsa_qbits_from_Q (int qbits ) +{ + if ((qbits%8) > 3) + { + log_error(_("ECDSA public key is expected to be in SEC encoding " + "multiple of 8 bits\n")); + return 0; + } + qbits -= qbits%8; + qbits /= 2; + return qbits; } - - - - diff --git a/g10/parse-packet.c b/g10/parse-packet.c index d43ab2c..5df336e 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -939,40 +939,47 @@ parse_pubkeyenc (IOBUF inp, int pkttype, unsigned long pktlen, } else { - if( k->pubkey_algo != PUBKEY_ALGO_ECDH ) { - for (i = 0; i < ndata; i++) - { - n = pktlen; - k->data[i] = mpi_read (inp, &n, 0); - pktlen -= n; - if (list_mode) - { - es_fprintf (listfp, "\tdata: "); - mpi_print (listfp, k->data[i], mpi_print_mode); - es_putc ('\n', listfp); - } - if (!k->data[i]) - rc = gpg_error (GPG_ERR_INV_PACKET); - } - } - else + if (k->pubkey_algo == PUBKEY_ALGO_ECDH) { - byte encr_buf[255]; - assert( ndata == 2 ); - n = pktlen; k->data[0] = mpi_read(inp, &n, 0); pktlen -=n; - rc = iobuf_read_size_body( inp, encr_buf, sizeof(encr_buf), pktlen, k->data+1 ); - if( rc ) - goto leave; - if( list_mode ) { - es_fprintf (listfp, "\tdata: "); - mpi_print(listfp, k->data[0], mpi_print_mode ); - es_putc ('\n', listfp); - es_fprintf (listfp, "\tdata: [% 3d bytes] ", encr_buf[0]+1); - mpi_print(listfp, k->data[1], mpi_print_mode ); - es_putc ('\n', listfp); - } - pktlen -= (encr_buf[0]+1); - } + byte encr_buf[255]; + + assert (ndata == 2); + n = pktlen; + k->data[0] = mpi_read (inp, &n, 0); + pktlen -= n; + rc = iobuf_read_size_body (inp, encr_buf, sizeof(encr_buf), + pktlen, k->data+1); + if (rc) + goto leave; + + if (list_mode) + { + es_fprintf (listfp, "\tdata: "); + mpi_print (listfp, k->data[0], mpi_print_mode ); + es_putc ('\n', listfp); + es_fprintf (listfp, "\tdata: [% 3d bytes] ", encr_buf[0]+1); + mpi_print (listfp, k->data[1], mpi_print_mode ); + es_putc ('\n', listfp); + } + pktlen -= (encr_buf[0]+1); + } + else + { + for (i = 0; i < ndata; i++) + { + n = pktlen; + k->data[i] = mpi_read (inp, &n, 0); + pktlen -= n; + if (list_mode) + { + es_fprintf (listfp, "\tdata: "); + mpi_print (listfp, k->data[i], mpi_print_mode); + es_putc ('\n', listfp); + } + if (!k->data[i]) + rc = gpg_error (GPG_ERR_INV_PACKET); + } + } } leave: @@ -1946,61 +1953,74 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, else { /* Fill in public key parameters. */ - if( algorithm != PUBKEY_ALGO_ECDSA && algorithm != PUBKEY_ALGO_ECDH ) { - 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]) - err = gpg_error (GPG_ERR_INV_PACKET); - } - } - else { - /* note that the code in this function ignores the errors */ - byte name_oid[256]; - err = iobuf_read_size_body( inp, name_oid, sizeof(name_oid), pktlen, pk->pkey+0 ); - if( err ) - goto leave; - n = name_oid[0]; - if( list_mode ) - es_fprintf (listfp, "\tpkey[0]: curve OID [%d] ...%02x %02x\n", - n, name_oid[1+n-2], name_oid[1+n-1] ); - pktlen -= (n+1); - /* set item [1], which corresponds to the public key; these two fields are all we need to uniquely define the key */ - // log_debug("Parsing ecc public key in the public packet, pktlen=%lu\n", pktlen); - n = pktlen; pk->pkey[1] = mpi_read( inp, &n, 0 ); pktlen -=n; - if( pk->pkey[1]==NULL ) - err = gpg_error(G10ERR_INVALID_PACKET); - else if( list_mode ) { - es_fprintf (listfp, "\tpkey[1]: "); - mpi_print(listfp, pk->pkey[1], mpi_print_mode); - es_putc ('\n', listfp); + if (algorithm == PUBKEY_ALGO_ECDSA && algorithm == PUBKEY_ALGO_ECDH) + { + /* FIXME: The code in this function ignores the errors. */ + byte name_oid[256]; + + err = iobuf_read_size_body (inp, name_oid, sizeof(name_oid), + pktlen, pk->pkey+0); + if (err) + goto leave; + n = name_oid[0]; + if (list_mode) + es_fprintf (listfp, "\tpkey[0]: curve OID [%d] ...%02x %02x\n", + n, name_oid[1+n-2], name_oid[1+n-1]); + pktlen -= (n+1); + /* Set item [1], which corresponds to the public key; these + two fields are all we need to uniquely define the key/ */ + n = pktlen; + pk->pkey[1] = mpi_read( inp, &n, 0 ); + pktlen -=n; + if (!pk->pkey[1]) + err = gpg_error (GPG_ERR_INV_PACKET); + else if (list_mode) + { + es_fprintf (listfp, "\tpkey[1]: "); + mpi_print (listfp, pk->pkey[1], mpi_print_mode); + es_putc ('\n', listfp); } - /* One more field for ECDH */ - if( algorithm == PUBKEY_ALGO_ECDH ) { -#define kek_params name_oid - err = iobuf_read_size_body( inp, kek_params, sizeof(kek_params), pktlen, pk->pkey+2 ); - if( err ) - goto leave; - n = kek_params[0]; - if( kek_params[1] != 1 ) { - log_error("invalid ecdh KEK parameters field type in private key: understand type 1, but found 0x%02x\n", kek_params[1]); - err = gpg_error(G10ERR_INVALID_PACKET); - goto leave; - } - if( list_mode ) - es_fprintf (listfp, "\tpkey[2]: KEK params type=01 hash:%d sym-algo:%d\n", kek_params[1+n-2], kek_params[1+n-1] ); - pktlen -= (n+1); -#undef kek_params - } - } + /* One more field for ECDH. */ + if (algorithm == PUBKEY_ALGO_ECDH) + { + /* (NAMEOID holds the KEK params.) */ + err = iobuf_read_size_body (inp, name_oid, sizeof(name_oid), + pktlen, pk->pkey+2); + if (err) + goto leave; + n = name_oid[0]; + if (name_oid[1] != 1) + { + log_error ("invalid ecdh KEK parameters field type in " + "private key: understand type 1, " + "but found 0x%02x\n", name_oid[1]); + err = gpg_error (GPG_ERR_INV_PACKET); + goto leave; + } + if (list_mode) + es_fprintf (listfp, "\tpkey[2]: KEK params type=01 " + "hash:%d sym-algo:%d\n", + name_oid[1+n-2], name_oid[1+n-1]); + pktlen -= (n+1); + } + } + else + { + 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]) + err = gpg_error (GPG_ERR_INV_PACKET); + } + } if (err) goto leave; } diff --git a/g10/pkglue.c b/g10/pkglue.c index 9050cc2..f5c8597 100644 --- a/g10/pkglue.c +++ b/g10/pkglue.c @@ -1,5 +1,5 @@ /* pkglue.c - public key operations glue code - * Copyright (C) 2000, 2003 Free Software Foundation, Inc. + * Copyright (C) 2000, 2003, 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -29,7 +29,8 @@ #include "pkglue.h" #include "main.h" - +/* FIXME: Better chnage the fucntion name because mpi_ is used by + gcrypt macros. */ gcry_mpi_t mpi_from_sexp (gcry_sexp_t sexp, const char * item) { @@ -45,101 +46,37 @@ mpi_from_sexp (gcry_sexp_t sexp, const char * item) } -/**************** - * Emulate our old PK interface here - sometime in the future we might - * change the internal design to directly fit to libgcrypt. - */ -int -pk_sign (int algo, gcry_mpi_t * data, gcry_mpi_t hash, gcry_mpi_t * skey) -{ - gcry_sexp_t s_sig, s_hash, s_skey; - int rc; - int gcry_pkalgo = map_pk_openpgp_to_gcry( algo ); - - /* make a sexp from skey */ - if (gcry_pkalgo == GCRY_PK_DSA) - { - rc = gcry_sexp_build (&s_skey, NULL, - "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))", - skey[0], skey[1], skey[2], skey[3], skey[4]); - } - else if (gcry_pkalgo == GCRY_PK_RSA || gcry_pkalgo == GCRY_PK_RSA_S) - { - rc = gcry_sexp_build (&s_skey, NULL, - "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))", - skey[0], skey[1], skey[2], skey[3], skey[4], - skey[5]); - } - else if (gcry_pkalgo == GCRY_PK_ELG || gcry_pkalgo == GCRY_PK_ELG_E) - { - rc = gcry_sexp_build (&s_skey, NULL, - "(private-key(elg(p%m)(g%m)(y%m)(x%m)))", - skey[0], skey[1], skey[2], skey[3]); - } - else if (gcry_pkalgo == GCRY_PK_ECDSA) - { - rc = gcry_sexp_build (&s_skey, NULL, - "(private-key(ecdsa(c%m)(q%m)(d%m)))", - skey[0], skey[1], skey[2] ); - } - else - return GPG_ERR_PUBKEY_ALGO; - - if (rc) - BUG (); - - /* put hash into a S-Exp s_hash */ - if (gcry_sexp_build (&s_hash, NULL, "%m", hash)) - BUG (); - - rc = gcry_pk_sign (&s_sig, s_hash, s_skey); - gcry_sexp_release (s_hash); - gcry_sexp_release (s_skey); - - if (rc) - ; - else if (algo == GCRY_PK_RSA || algo == GCRY_PK_RSA_S) - data[0] = mpi_from_sexp (s_sig, "s"); - else - { - data[0] = mpi_from_sexp (s_sig, "r"); - data[1] = mpi_from_sexp (s_sig, "s"); - } - - gcry_sexp_release (s_sig); - return rc; -} /**************** * Emulate our old PK interface here - sometime in the future we might * change the internal design to directly fit to libgcrypt. */ int -pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey) +pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey) { gcry_sexp_t s_sig, s_hash, s_pkey; int rc; - const int gcry_pkalgo = map_pk_openpgp_to_gcry( algo ); + const int pkalgo = map_pk_openpgp_to_gcry (algo); - /* make a sexp from pkey */ - if (gcry_pkalgo == GCRY_PK_DSA) + /* Make a sexp from pkey. */ + if (pkalgo == GCRY_PK_DSA) { rc = gcry_sexp_build (&s_pkey, NULL, "(public-key(dsa(p%m)(q%m)(g%m)(y%m)))", pkey[0], pkey[1], pkey[2], pkey[3]); } - else if (gcry_pkalgo == GCRY_PK_ELG || gcry_pkalgo == GCRY_PK_ELG_E) + else if (pkalgo == GCRY_PK_ELG || pkalgo == GCRY_PK_ELG_E) { rc = gcry_sexp_build (&s_pkey, NULL, "(public-key(elg(p%m)(g%m)(y%m)))", pkey[0], pkey[1], pkey[2]); } - else if (gcry_pkalgo == GCRY_PK_RSA || gcry_pkalgo == GCRY_PK_RSA_S) + else if (pkalgo == GCRY_PK_RSA || pkalgo == GCRY_PK_RSA_S) { rc = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]); } - else if (gcry_pkalgo == GCRY_PK_ECDSA) /* same as GCRY_PK_ECDH */ + else if (pkalgo == GCRY_PK_ECDSA) /* Same as GCRY_PK_ECDH */ { rc = gcry_sexp_build (&s_pkey, NULL, "(public-key(ecdsa(c%m)(q%m)))", pkey[0], pkey[1]); @@ -150,13 +87,13 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey) if (rc) BUG (); /* gcry_sexp_build should never fail. */ - /* put hash into a S-Exp s_hash */ + /* Put hash into a S-Exp s_hash. */ if (gcry_sexp_build (&s_hash, NULL, "%m", hash)) BUG (); /* gcry_sexp_build should never fail. */ /* Put data into a S-Exp s_sig. */ s_sig = NULL; - if (gcry_pkalgo == GCRY_PK_DSA) + if (pkalgo == GCRY_PK_DSA) { if (!data[0] || !data[1]) rc = gpg_error (GPG_ERR_BAD_MPI); @@ -164,7 +101,7 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey) rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(dsa(r%m)(s%m)))", data[0], data[1]); } - else if (gcry_pkalgo == GCRY_PK_ECDSA) + else if (pkalgo == GCRY_PK_ECDSA) { if (!data[0] || !data[1]) rc = gpg_error (GPG_ERR_BAD_MPI); @@ -172,7 +109,7 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey) rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(ecdsa(r%m)(s%m)))", data[0], data[1]); } - else if (gcry_pkalgo == GCRY_PK_ELG || gcry_pkalgo == GCRY_PK_ELG_E) + else if (pkalgo == GCRY_PK_ELG || pkalgo == GCRY_PK_ELG_E) { if (!data[0] || !data[1]) rc = gpg_error (GPG_ERR_BAD_MPI); @@ -180,7 +117,7 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey) rc = gcry_sexp_build (&s_sig, NULL, "(sig-val(elg(r%m)(s%m)))", data[0], data[1]); } - else if (gcry_pkalgo == GCRY_PK_RSA || gcry_pkalgo == GCRY_PK_RSA_S) + else if (pkalgo == GCRY_PK_RSA || pkalgo == GCRY_PK_RSA_S) { if (!data[0]) rc = gpg_error (GPG_ERR_BAD_MPI); @@ -207,12 +144,13 @@ pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t * data, gcry_mpi_t * pkey) * change the internal design to directly fit to libgcrypt. */ int -pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t * pkey) +pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, + const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t *pkey) { gcry_sexp_t s_ciph, s_data, s_pkey; int rc; - /* make a sexp from pkey */ + /* Make a sexp from pkey. */ if (algo == GCRY_PK_ELG || algo == GCRY_PK_ELG_E) { rc = gcry_sexp_build (&s_pkey, NULL, @@ -227,7 +165,7 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, const byte pk_fp[MAX } else if (algo == PUBKEY_ALGO_ECDH) { - return pk_ecdh_encrypt( resarr, pk_fp, data, pkey ); + return pk_ecdh_encrypt (resarr, pk_fp, data, pkey); } else return GPG_ERR_PUBKEY_ALGO; @@ -235,11 +173,11 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, const byte pk_fp[MAX if (rc) BUG (); - /* put the data into a simple list */ + /* Put the data into a simple list. */ if (gcry_sexp_build (&s_data, NULL, "%m", data)) BUG (); - /* pass it to libgcrypt */ + /* Pass it to libgcrypt. */ rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey); gcry_sexp_release (s_data); gcry_sexp_release (s_pkey); @@ -247,9 +185,11 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, const byte pk_fp[MAX if (rc) ; else - { /* add better error handling or make gnupg use S-Exp directly */ + { /* Add better error handling or make gnupg use S-Exp directly. */ resarr[0] = mpi_from_sexp (s_ciph, "a"); - if (algo != GCRY_PK_RSA && algo != GCRY_PK_RSA_E && algo != PUBKEY_ALGO_ECDH) + if (algo != GCRY_PK_RSA + && algo != GCRY_PK_RSA_E + && algo != PUBKEY_ALGO_ECDH) resarr[1] = mpi_from_sexp (s_ciph, "b"); } @@ -257,6 +197,7 @@ pk_encrypt (int algo, gcry_mpi_t * resarr, gcry_mpi_t data, const byte pk_fp[MAX return rc; } + /* Check whether SKEY is a suitable secret key. */ int pk_check_secret_key (int algo, gcry_mpi_t *skey) diff --git a/g10/pkglue.h b/g10/pkglue.h index a1c821d..0ceb43f 100644 --- a/g10/pkglue.h +++ b/g10/pkglue.h @@ -1,5 +1,5 @@ /* pkglue.h - public key operations definitions - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -22,21 +22,19 @@ gcry_mpi_t mpi_from_sexp (gcry_sexp_t sexp, const char * item); -int pk_sign (int algo, gcry_mpi_t *data, gcry_mpi_t hash, - gcry_mpi_t *skey); int pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey); int pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, const byte fp[MAX_FINGERPRINT_LEN], gcry_mpi_t *pkey); -int pk_decrypt (int algo, gcry_mpi_t *result, const byte fp[MAX_FINGERPRINT_LEN], gcry_mpi_t *data, - gcry_mpi_t *skey); int pk_check_secret_key (int algo, gcry_mpi_t *skey); -int pk_ecdh_encrypt (gcry_mpi_t * resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t * pkey); -int pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t shared, gcry_mpi_t * skey); +int pk_ecdh_encrypt (gcry_mpi_t *resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], + gcry_mpi_t data, gcry_mpi_t * pkey); +int pk_ecdh_decrypt (gcry_mpi_t *result, const byte sk_fp[MAX_FINGERPRINT_LEN], + gcry_mpi_t data, gcry_mpi_t shared, gcry_mpi_t * skey); -gcry_mpi_t pk_ecdh_default_params_to_mpi( int qbits ); -byte *pk_ecdh_default_params( int qbits, size_t *sizeout ); +gcry_mpi_t pk_ecdh_default_params_to_mpi (int qbits); +byte *pk_ecdh_default_params (int qbits, size_t *sizeout); #endif /*GNUPG_G10_PKGLUE_H*/ diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index 24411e8..ddca41e 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -218,68 +218,72 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) log_printhex ("DEK frame:", frame, nframe); n = 0; - if( sk->pubkey_algo != PUBKEY_ALGO_ECDH ) { - if (!card) - { - if (n + 7 > nframe) - { - err = gpg_error (G10ERR_WRONG_SECKEY); - goto leave; - } - if (frame[n] == 1 && frame[nframe - 1] == 2) - { - log_info (_("old encoding of the DEK is not supported\n")); - err = gpg_error (G10ERR_CIPHER_ALGO); - goto leave; - } - if (frame[n] != 2) /* Something went wrong. */ - { - err = gpg_error (G10ERR_WRONG_SECKEY); - goto leave; - } - for (n++; n < nframe && frame[n]; n++) /* Skip the random bytes. */ - ; - n++; /* Skip the zero byte. */ - } - } - else { - gcry_mpi_t shared_mpi; - gcry_mpi_t decoded; - - /* at the beginning the frame is the bytes of shared point MPI */ - - err = gcry_mpi_scan (&shared_mpi, GCRYMPI_FMT_USG, frame, nframe, NULL); - if (err) { - log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); - goto leave; - } + if (sk->pubkey_algo == PUBKEY_ALGO_ECDH) + { + gcry_mpi_t shared_mpi; + gcry_mpi_t decoded; + + /* At the beginning the frame are the bytes of shared point MPI. */ + err = gcry_mpi_scan (&shared_mpi, GCRYMPI_FMT_USG, frame, nframe, NULL); + if (err) + { + log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); + goto leave; + } - err = pk_ecdh_decrypt (&decoded, fp, enc->data[1]/*encr data as an MPI*/, shared_mpi, sk->pkey); - mpi_release( shared_mpi ); - if( err ) - goto leave; + err = pk_ecdh_decrypt (&decoded, fp, enc->data[1]/*encr data as an MPI*/, + shared_mpi, sk->pkey); + mpi_release (shared_mpi); + if(err) + goto leave; - /* reuse nframe, which size is sufficient to include the session key */ - err = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &nframe, decoded); - mpi_release( decoded ); - if( err ) - goto leave; + /* Reuse NFRAME, which size is sufficient to include the session key. */ + err = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &nframe, decoded); + mpi_release (decoded); + if (err) + goto leave; - /* Now the frame is the bytes decrypted but padded session key */ + /* Now the frame are the bytes decrypted but padded session key. */ - /* Allow double padding for the benefit of DEK size concealment. - * Higher than this is wasteful. - */ - if( frame[nframe-1] > 8*2 || nframe <= 8 ) { - err = G10ERR_WRONG_SECKEY; goto leave; + /* Allow double padding for the benefit of DEK size concealment. + Higher than this is wasteful. */ + if (frame[nframe-1] > 8*2 || nframe <= 8) + { + err = gpg_error (GPG_ERR_WRONG_SECKEY); + goto leave; + } + nframe -= frame[nframe-1]; /* Remove padding. */ + assert (n); /* (used just below) */ + } + else + { + if (!card) + { + if (n + 7 > nframe) + { + err = gpg_error (GPG_ERR_WRONG_SECKEY); + goto leave; + } + if (frame[n] == 1 && frame[nframe - 1] == 2) + { + log_info (_("old encoding of the DEK is not supported\n")); + err = gpg_error (GPG_ERR_CIPHER_ALGO); + goto leave; + } + if (frame[n] != 2) /* Something went wrong. */ + { + err = gpg_error (GPG_ERR_WRONG_SECKEY); + goto leave; + } + for (n++; n < nframe && frame[n]; n++) /* Skip the random bytes. */ + ; + n++; /* Skip the zero byte. */ + } } - nframe -= frame[nframe-1]; /* remove padding */ - assert( n==0 ); /* used just bellow */ - } if (n + 4 > nframe) { - err = gpg_error (G10ERR_WRONG_SECKEY); + err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } diff --git a/g10/seskey.c b/g10/seskey.c index e50cf5c..fa6765d 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -1,6 +1,6 @@ /* seskey.c - make sesssion keys etc. * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, - * 2006, 2009 Free Software Foundation, Inc. + * 2006, 2009, 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -76,109 +76,125 @@ make_session_key( DEK *dek ) gcry_mpi_t encode_session_key (int openpgp_pk_algo, DEK *dek, unsigned int nbits) { - size_t nframe = (nbits+7) / 8; - byte *p; - byte *frame; - int i,n; - u16 csum = 0; - gcry_mpi_t a; - - if( DBG_CIPHER ) - log_debug("encode_session_key: encoding %d byte DEK", dek->keylen); - - for( p = dek->key, i=0; i < dek->keylen; i++ ) - csum += *p++; - - /* Shortcut for ECDH. It's padding is minimal to simply make the output be a multiple of 8 bytes. */ - if( openpgp_pk_algo == PUBKEY_ALGO_ECDH ) { - /* pad to 8 byte granulatiry; the padding byte is the number of padded bytes. - * A DEK(k bytes) CSUM(2 bytes) 0x 0x 0x 0x ... 0x - * +---- x times ---+ - */ - nframe = ( 1 + dek->keylen + 2 /* the value so far is always odd */ + 7 ) & (~7); - assert( !(nframe%8) && nframe > 1 + dek->keylen + 2 ); /* alg+key+csum fit and the size is congruent to 8 */ - frame = xmalloc_secure( nframe ); - n = 0; - frame[n++] = dek->algo; - memcpy( frame+n, dek->key, dek->keylen ); n += dek->keylen; - frame[n++] = csum >>8; - frame[n++] = csum; - i = nframe - n; /* number padded bytes */ - memset( frame+n, i, i );/* use it as the value of each padded byte */ - assert( n+i == nframe ); - - if( DBG_CIPHER ) - log_debug("encode_session_key: [%d] %02x %02x %02x ... %02x %02x %02x", nframe, frame[0],frame[1],frame[2], frame[nframe-3],frame[nframe-2],frame[nframe-1]); - - if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, nframe, &nframe)) - BUG(); - xfree(frame); - return a; + size_t nframe = (nbits+7) / 8; + byte *p; + byte *frame; + int i,n; + u16 csum; + gcry_mpi_t a; + + if (DBG_CIPHER) + log_debug ("encode_session_key: encoding %d byte DEK", dek->keylen); + + csum = 0; + for (p = dek->key, i=0; i < dek->keylen; i++) + csum += *p++; + + /* Shortcut for ECDH. It's padding is minimal to simply make the + output be a multiple of 8 bytes. */ + if (openpgp_pk_algo == PUBKEY_ALGO_ECDH) + { + /* Pad to 8 byte granulatiry; the padding byte is the number of + * padded bytes. + * + * A DEK(k bytes) CSUM(2 bytes) 0x 0x 0x 0x ... 0x + * +---- x times ---+ + */ + nframe = (( 1 + dek->keylen + 2 /* The value so far is always odd. */ + + 7 ) & (~7)); + + /* alg+key+csum fit and the size is congruent to 8. */ + assert (!(nframe%8) && nframe > 1 + dek->keylen + 2 ); + + frame = xmalloc_secure (nframe); + n = 0; + frame[n++] = dek->algo; + memcpy (frame+n, dek->key, dek->keylen); + n += dek->keylen; + frame[n++] = csum >> 8; + frame[n++] = csum; + i = nframe - n; /* Number of padded bytes. */ + memset (frame+n, i, i); /* Use it as the value of each padded byte. */ + assert (n+i == nframe); + + if (DBG_CIPHER) + log_debug ("encode_session_key: " + "[%d] %02x %02x %02x ... %02x %02x %02x\n", + nframe, frame[0], frame[1], frame[2], + frame[nframe-3], frame[nframe-2], frame[nframe-1]); + + if (gcry_mpi_scan (&a, GCRYMPI_FMT_USG, frame, nframe, &nframe)) + BUG(); + xfree(frame); + return a; } - - /* The current limitation is that we can only use a session key - * whose length is a multiple of BITS_PER_MPI_LIMB - * I think we can live with that. - */ - if( dek->keylen + 7 > nframe || !nframe ) - log_bug("can't encode a %d bit key in a %d bits frame\n", - dek->keylen*8, nbits ); - - /* We encode the session key in this way: - * - * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) - * - * (But how can we store the leading 0 - the external representaion - * of MPIs doesn't allow leading zeroes =:-) - * - * RND are non-zero random bytes. - * A is the cipher algorithm - * DEK is the encryption key (session key) length k depends on the - * cipher algorithm (20 is used with blowfish160). - * CSUM is the 16 bit checksum over the DEK - */ - - frame = xmalloc_secure( nframe ); - n = 0; - frame[n++] = 0; - frame[n++] = 2; - i = nframe - 6 - dek->keylen; - assert( i > 0 ); - p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM); - /* Replace zero bytes by new values. */ - for(;;) { - int j, k; - byte *pp; - - /* count the zero bytes */ - for(j=k=0; j < i; j++ ) - if( !p[j] ) - k++; - if( !k ) - break; /* okay: no zero bytes */ - k += k/128 + 3; /* better get some more */ - pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM); - for(j=0; j < i && k ;) { - if( !p[j] ) - p[j] = pp[--k]; - if (p[j]) - j++; + + /* The current limitation is that we can only use a session key + * whose length is a multiple of BITS_PER_MPI_LIMB + * I think we can live with that. + */ + if (dek->keylen + 7 > nframe || !nframe) + log_bug ("can't encode a %d bit key in a %d bits frame\n", + dek->keylen*8, nbits ); + + /* We encode the session key in this way: + * + * 0 2 RND(n bytes) 0 A DEK(k bytes) CSUM(2 bytes) + * + * (But how can we store the leading 0 - the external representaion + * of MPIs doesn't allow leading zeroes =:-) + * + * RND are non-zero random bytes. + * A is the cipher algorithm + * DEK is the encryption key (session key) length k depends on the + * cipher algorithm (20 is used with blowfish160). + * CSUM is the 16 bit checksum over the DEK + */ + + frame = xmalloc_secure( nframe ); + n = 0; + frame[n++] = 0; + frame[n++] = 2; + i = nframe - 6 - dek->keylen; + assert( i > 0 ); + p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM); + /* Replace zero bytes by new values. */ + for (;;) + { + int j, k; + byte *pp; + + /* Count the zero bytes. */ + for (j=k=0; j < i; j++ ) + if (!p[j]) + k++; + if (!k) + break; /* Okay: no zero bytes. */ + k += k/128 + 3; /* Better get some more. */ + pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM); + for (j=0; j < i && k ;) + { + if (!p[j]) + p[j] = pp[--k]; + if (p[j]) + j++; } - xfree(pp); + xfree (pp); } - memcpy( frame+n, p, i ); - xfree(p); - n += i; - frame[n++] = 0; - frame[n++] = dek->algo; - memcpy( frame+n, dek->key, dek->keylen ); n += dek->keylen; - frame[n++] = csum >>8; - frame[n++] = csum; - assert( n == nframe ); - if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, n, &nframe)) - BUG(); - xfree(frame); - return a; + memcpy (frame+n, p, i); + xfree (p); + n += i; + frame[n++] = 0; + frame[n++] = dek->algo; + memcpy (frame+n, dek->key, dek->keylen ); + n += dek->keylen; + frame[n++] = csum >>8; + frame[n++] = csum; + assert (n == nframe); + if (gcry_mpi_scan( &a, GCRYMPI_FMT_USG, frame, n, &nframe)) + BUG(); + xfree (frame); + return a; } @@ -192,8 +208,8 @@ do_encode_md( gcry_md_hd_t md, int algo, size_t len, unsigned nbits, gcry_mpi_t a; if( len + asnlen + 4 > nframe ) - log_bug("can't encode a %d bit MD into a %d bits frame, algo=%d\n", - (int)(len*8), (int)nbits, algo); + log_bug ("can't encode a %d bit MD into a %d bits frame, algo=%d\n", + (int)(len*8), (int)nbits, algo); /* We encode the MD in this way: * @@ -240,26 +256,27 @@ gcry_mpi_t encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo) { gcry_mpi_t frame; - int gcry_pkalgo; + int pkalgo; assert (hash_algo); assert (pk); - gcry_pkalgo = map_pk_openpgp_to_gcry( pk->pubkey_algo ); + pkalgo = map_pk_openpgp_to_gcry (pk->pubkey_algo); - if (gcry_pkalgo == GCRY_PK_DSA || gcry_pkalgo == GCRY_PK_ECDSA ) + if (pkalgo == GCRY_PK_DSA || pkalgo == GCRY_PK_ECDSA) { - /* It's a DSA signature, so find out the size of q. */ + /* It's a DSA signature, so find out the size of q. */ size_t qbytes = gcry_mpi_get_nbits (pk->pkey[1]); - /* pkey[1] is Q for ECDSA, which is an uncompressed point, i.e. 04 */ - if( gcry_pkalgo==GCRY_PK_ECDSA ) - qbytes = ecdsa_qbits_from_Q( qbytes ); - + /* pkey[1] is Q for ECDSA, which is an uncompressed point, + i.e. 04 */ + if (pkalgo == GCRY_PK_ECDSA) + qbytes = ecdsa_qbits_from_Q (qbytes); + /* Make sure it is a multiple of 8 bits. */ - - if(qbytes%8) + + if (qbytes%8) { log_error(_("DSA requires the hash length to be a" " multiple of 8 bits\n")); @@ -275,30 +292,38 @@ encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo) if (qbytes < 160) { log_error (_("%s key %s uses an unsafe (%zu bit) hash\n"), - gcry_pk_algo_name( gcry_pkalgo ), - keystr_from_pk (pk), qbytes); + gcry_pk_algo_name (pkalgo), keystr_from_pk (pk), qbytes); return NULL; } - + qbytes /= 8; /* Check if we're too short. Too long is safe as we'll - automatically left-truncate. */ - /* This checks would require the use of SHA512 with ECDSA 512. I think this is overkill to fail in this case. - * Therefore, relax the check, but only for ECDSA keys. We may need to adjust it later for general case. - * ( Note that the check will never pass for ECDSA 521 anyway as the only hash that intended to match it is SHA 512, but 512 < 521 ). - */ - if (gcry_md_get_algo_dlen (hash_algo) < ((gcry_pkalgo==GCRY_PK_ECDSA && qbytes>(521)/8) ? 512/8 : qbytes) ) + automatically left-truncate. + + FIXME: Check against FIPS. + This checks would require the use of SHA512 with ECDSA 512. I + think this is overkill to fail in this case. Therefore, + relax the check, but only for ECDSA keys. We may need to + adjust it later for general case. (Note that the check will + never pass for ECDSA 521 anyway as the only hash that + intended to match it is SHA 512, but 512 < 521). */ + if (gcry_md_get_algo_dlen (hash_algo) + < ((pkalgo == GCRY_PK_ECDSA && qbytes > (521)/8) ? 512/8 : qbytes)) { - log_error (_("%s key %s requires a %zu bit or larger hash, used hash-algo=%d\n"), - gcry_pk_algo_name( gcry_pkalgo ), - keystr_from_pk(pk), qbytes*8, hash_algo); + log_error (_("%s key %s requires a %zu bit or larger hash " + "(hash is %s\n"), + gcry_pk_algo_name (pkalgo), + keystr_from_pk(pk), qbytes*8, + gcry_md_algo_name (hash_algo)); return NULL; } - /* Note that in case of ECDSA 521 hash is always smaller than the key size */ + /* Note that in case of ECDSA 521 hash is always smaller than + the key size. */ if (gcry_mpi_scan (&frame, GCRYMPI_FMT_USG, - gcry_md_read (md, hash_algo), gcry_md_get_algo_dlen (hash_algo), &qbytes)) + gcry_md_read (md, hash_algo), + gcry_md_get_algo_dlen (hash_algo), &qbytes)) BUG(); } else diff --git a/g10/sign.c b/g10/sign.c index ccf7964..30dc66d 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -436,14 +436,15 @@ hash_for (PKT_public_key *pk) { return recipient_digest_algo; } - else if(pk->pubkey_algo==PUBKEY_ALGO_DSA || pk->pubkey_algo==PUBKEY_ALGO_ECDSA ) + else if (pk->pubkey_algo == PUBKEY_ALGO_DSA + || pk->pubkey_algo == PUBKEY_ALGO_ECDSA) { unsigned int qbytes = gcry_mpi_get_nbits (pk->pkey[1]); - if( pk->pubkey_algo==PUBKEY_ALGO_ECDSA ) - qbytes = ecdsa_qbits_from_Q(qbytes); + if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA) + qbytes = ecdsa_qbits_from_Q (qbytes); qbytes = qbytes/8; - + /* It's a DSA key, so find a hash that is the same size as q or larger. If q is 160, assume it is an old DSA key and use a 160-bit hash unless --enable-dsa2 is set, in which case act @@ -924,12 +925,14 @@ sign_file (ctrl_t ctrl, strlist_t filenames, int detached, strlist_t locusr, for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next ) { - if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_DSA || sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA ) + if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_DSA + || sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA) { - int temp_hashlen = gcry_mpi_get_nbits(sk_rover->pk->pkey[1]); + int temp_hashlen = (gcry_mpi_get_nbits + (sk_rover->pk->pkey[1])); - if( sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA ) - temp_hashlen = ecdsa_qbits_from_Q( temp_hashlen ); + if (sk_rover->pk->pubkey_algo == PUBKEY_ALGO_ECDSA) + temp_hashlen = ecdsa_qbits_from_Q (temp_hashlen); temp_hashlen = (temp_hashlen+7)/8; /* Pick a hash that is large enough for our @@ -1482,13 +1485,14 @@ make_keysig_packet( PKT_signature **ret_sig, PKT_public_key *pk, if(opt.cert_digest_algo) digest_algo=opt.cert_digest_algo; - else if(pksk->pubkey_algo==PUBKEY_ALGO_RSA + else if(pksk->pubkey_algo == PUBKEY_ALGO_RSA && pk->version<4 && sigversion<4) digest_algo = DIGEST_ALGO_MD5; - else if(pksk->pubkey_algo==PUBKEY_ALGO_DSA) - digest_algo = match_dsa_hash (gcry_mpi_get_nbits (pksk->pkey[1])/8 ); - else if(pksk->pubkey_algo==PUBKEY_ALGO_ECDSA ) - digest_algo = match_dsa_hash (ecdsa_qbits_from_Q( gcry_mpi_get_nbits (pksk->pkey[1]) ) / 8); + else if(pksk->pubkey_algo == PUBKEY_ALGO_DSA) + digest_algo = match_dsa_hash (gcry_mpi_get_nbits (pksk->pkey[1])/8); + else if(pksk->pubkey_algo == PUBKEY_ALGO_ECDSA ) + digest_algo = match_dsa_hash (ecdsa_qbits_from_Q + (gcry_mpi_get_nbits (pksk->pkey[1]))/8); else digest_algo = DIGEST_ALGO_SHA1; } diff --git a/g10/verify-stubs.c b/g10/verify-stubs.c index d1f0aa1..c4c657b 100644 --- a/g10/verify-stubs.c +++ b/g10/verify-stubs.c @@ -1,6 +1,5 @@ /* To satisfy the linker for the gpgv target - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, - * 2007 Free Software Foundation, Inc. + * Copyright (C) 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -25,6 +24,8 @@ #include "main.h" int -pk_ecc_keypair_gen( PKT_public_key **pk_out, int algo, int keygen_flags, char **cache_nonce_addr, unsigned nbits) { - return GPG_ERR_NOT_IMPLEMENTED; +pk_ecc_keypair_gen (PKT_public_key **pk_out, int algo, int keygen_flags, + char **cache_nonce_addr, unsigned nbits) +{ + return GPG_ERR_NOT_IMPLEMENTED; } diff --git a/g13/utils.c b/g13/utils.c index 1ea7f32..4b374df 100644 --- a/g13/utils.c +++ b/g13/utils.c @@ -176,7 +176,5 @@ next_tuple (tupledesc_t tupledesc, unsigned int *r_tag, size_t *r_length) } return NULL; -} - - +} diff --git a/include/ChangeLog b/include/ChangeLog index 339800f..7c1b372 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,9 @@ +2011-01-21 Werner Koch + + * cipher.h (GCRY_PK_USAGE_CERT): Remove comaptibility macros + because we now require libgcrypt 1.4.6. + (GCRY_PK_ECDH): Add replacement. + 2009-08-20 Daiki Ueno (wk) * cipher.h (struct DEK): Add field S2K_CACHEID. diff --git a/include/cipher.h b/include/cipher.h index 65cd59e..03d38da 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -1,6 +1,6 @@ /* cipher.h - Definitions for OpenPGP * Copyright (C) 1998, 1999, 2000, 2001, 2006, - * 2007 Free Software Foundation, Inc. + * 2007, 2010 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -23,10 +23,8 @@ #include /* Macros for compatibility with older libgcrypt versions. */ -#ifndef GCRY_PK_USAGE_CERT -# define GCRY_PK_USAGE_CERT 4 -# define GCRY_PK_USAGE_AUTH 8 -# define GCRY_PK_USAGE_UNKN 128 +#ifndef HAVE_GCRY_PK_ECDSA +# define GCRY_PK_ECDH 302 #endif @@ -56,8 +54,8 @@ #define PUBKEY_ALGO_RSA_S /* 3 */ GCRY_PK_RSA_S /* RSA sign only. */ #define PUBKEY_ALGO_ELGAMAL_E /* 16 */ GCRY_PK_ELG_E /* Elgamal encr only */ #define PUBKEY_ALGO_DSA /* 17 */ GCRY_PK_DSA -#define PUBKEY_ALGO_ECDH 18 /* corresponds to GCRY_PK_ECDH ECC DH; encrypt only */ -#define PUBKEY_ALGO_ECDSA 19 /* corresponds to GCRY_PK_ECDSA ECC DSA; sign only */ +#define PUBKEY_ALGO_ECDH 18 +#define PUBKEY_ALGO_ECDSA 19 #define PUBKEY_ALGO_ELGAMAL /* 20 */ GCRY_PK_ELG /* Elgamal encr+sign */ #define PUBKEY_USAGE_SIG GCRY_PK_USAGE_SIGN /* Good for signatures. */ diff --git a/kbx/keybox-openpgp.c b/kbx/keybox-openpgp.c index 6c9410e..f1de685 100644 --- a/kbx/keybox-openpgp.c +++ b/kbx/keybox-openpgp.c @@ -245,6 +245,7 @@ parse_key (const unsigned char *data, size_t datalen, break; case 18: /* ECDH */ npkey = 3; + break; case 19: /* ECDSA */ npkey = 2; break; ----------------------------------------------------------------------- Summary of changes: ChangeLog | 5 + agent/ChangeLog | 4 + agent/cvt-openpgp.c | 31 ++-- agent/gpg-agent.c | 2 + agent/protect.c | 37 +--- common/convert.c | 11 +- configure.ac | 18 ++- dirmngr/Makefile.am | 2 +- g10/armor.c | 2 +- g10/build-packet.c | 87 ++++++---- g10/ecdh.c | 451 +++++++++++++++++++++++++++++--------------------- g10/encrypt.c | 4 +- g10/export.c | 22 +-- g10/gpg.c | 2 +- g10/keygen.c | 2 +- g10/keyid.c | 37 +++-- g10/main.h | 16 ++- g10/misc.c | 133 ++++++++------- g10/parse-packet.c | 194 ++++++++++++---------- g10/pkglue.c | 111 +++---------- g10/pkglue.h | 16 +- g10/pubkey-enc.c | 112 +++++++------ g10/seskey.c | 279 +++++++++++++++++-------------- g10/sign.c | 30 ++-- g10/verify-stubs.c | 9 +- g13/utils.c | 4 +- include/ChangeLog | 6 + include/cipher.h | 12 +- kbx/keybox-openpgp.c | 1 + 29 files changed, 875 insertions(+), 765 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Fri Jan 21 16:28:23 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Fri, 21 Jan 2011 16:28:23 +0100 Subject: [git] GnuPG - branch, ECC-INTEGRATION-2-1, updated. gnupg-2.1.0beta1-40-gc3db770 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, ECC-INTEGRATION-2-1 has been updated via c3db7705c049e31e678ff87e230b8160aa0027f1 (commit) via 27929981fc23fabecf6af9fa1361361b821bb2fd (commit) from 90b0ff23b7e51332592668e4034967c1aac1c593 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit c3db7705c049e31e678ff87e230b8160aa0027f1 Author: Werner Koch Date: Fri Jan 21 15:58:07 2011 +0100 Truncate the DSA hash; fixes regression. Removed left over debug code. diff --git a/g10/ChangeLog b/g10/ChangeLog index 75415f4..8e79587 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,5 +1,7 @@ 2011-01-21 Werner Koch + * seskey.c (encode_md_value): Truncate the DSA hash again. + * misc.c (openpgp_pk_algo_name): Always use the gcrypt function. 2010-12-09 Werner Koch diff --git a/g10/seskey.c b/g10/seskey.c index fa6765d..2d7918d 100644 --- a/g10/seskey.c +++ b/g10/seskey.c @@ -319,11 +319,13 @@ encode_md_value (PKT_public_key *pk, gcry_md_hd_t md, int hash_algo) return NULL; } - /* Note that in case of ECDSA 521 hash is always smaller than - the key size. */ + /* By passing QBYTES as length to mpi_scan, we do the truncation + of the hash. + + Note that in case of ECDSA 521 the hash is always smaller + than the key size. */ if (gcry_mpi_scan (&frame, GCRYMPI_FMT_USG, - gcry_md_read (md, hash_algo), - gcry_md_get_algo_dlen (hash_algo), &qbytes)) + gcry_md_read (md, hash_algo), qbytes, &qbytes)) BUG(); } else diff --git a/g10/sign.c b/g10/sign.c index cbb3c62..30dc66d 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -298,9 +298,6 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig, { PKT_public_key *pk = xmalloc_clear (sizeof *pk); - log_debug ("checking created signature algo=%d\n", mdalgo); - log_printhex ("md:", dp, gcry_md_get_algo_dlen (mdalgo)); - if (get_pubkey (pk, sig->keyid )) err = gpg_error (GPG_ERR_NO_PUBKEY); else commit 27929981fc23fabecf6af9fa1361361b821bb2fd Author: Werner Koch Date: Fri Jan 21 15:22:41 2011 +0100 Make most of the selftests work. Note that there is still a problem with tests/openpgp/sigs.test while using the option --digest-algo SHA256. diff --git a/agent/ChangeLog b/agent/ChangeLog index 6992827..4b0712c 100644 --- a/agent/ChangeLog +++ b/agent/ChangeLog @@ -1,5 +1,7 @@ 2011-01-21 Werner Koch + * pksign.c (do_encode_dsa): Compare MDLEN to bytes. + * cvt-openpgp.c (GCRY_PK_ECDH) [!HAVE_GCRY_PK_ECDH]: New. 2010-12-02 Werner Koch diff --git a/agent/pksign.c b/agent/pksign.c index a6dbf25..0414bc3 100644 --- a/agent/pksign.c +++ b/agent/pksign.c @@ -113,21 +113,21 @@ get_dsa_qbits (gcry_sexp_t key) /* Encode a message digest for use with an DSA algorithm. */ static gpg_error_t -do_encode_dsa (const byte * md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey, +do_encode_dsa (const byte *md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey, gcry_sexp_t *r_hash) { gpg_error_t err; gcry_sexp_t hash; unsigned int qbits; - int gcry_pkalgo; + int pkalgo; *r_hash = NULL; - gcry_pkalgo = map_pk_openpgp_to_gcry( dsaalgo ); + pkalgo = map_pk_openpgp_to_gcry (dsaalgo); - if (gcry_pkalgo == GCRY_PK_ECDSA) + if (pkalgo == GCRY_PK_ECDSA) qbits = gcry_pk_get_nbits (pkey); - else if (gcry_pkalgo == GCRY_PK_DSA) + else if (pkalgo == GCRY_PK_DSA) qbits = get_dsa_qbits (pkey); else return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO); @@ -146,25 +146,28 @@ do_encode_dsa (const byte * md, size_t mdlen, int dsaalgo, gcry_sexp_t pkey, if (qbits < 160) { log_error (_("%s key uses an unsafe (%u bit) hash\n"), - gcry_pk_algo_name (gcry_pkalgo), qbits); + gcry_pk_algo_name (pkalgo), qbits); return gpg_error (GPG_ERR_INV_LENGTH); } /* Check if we're too short. Too long is safe as we'll - automatically left-truncate. */ - - /* This check would require the use of SHA512 with ECDSA 512. I think this is overkill to fail in this case. - * Therefore, relax the check, but only for ECDSA keys. We may need to adjust it later for general case. - * ( Note that the check is really a bug for ECDSA 521 as the only hash that matches it is SHA 512, but 512 < 521 ). + * automatically left-truncate. + * + * This check would require the use of SHA512 with ECDSA 512. I + * think this is overkill to fail in this case. Therefore, relax + * the check, but only for ECDSA keys. We may need to adjust it + * later for general case. (Note that the check is really a bug for + * ECDSA 521 as the only hash that matches it is SHA 512, but 512 < + * 521 ). */ - if( mdlen < ((gcry_pkalgo==GCRY_PK_ECDSA && qbits>521) ? 512 : qbits) ) + if (mdlen < ((pkalgo==GCRY_PK_ECDSA && qbits > 521) ? 512 : qbits)/8) { log_error (_("a %zu bit hash is not valid for a %u bit %s key\n"), - mdlen, + mdlen*8, gcry_pk_get_nbits (pkey), - gcry_pk_algo_name (gcry_pkalgo)); + gcry_pk_algo_name (pkalgo)); /* FIXME: we need to check the requirements for ECDSA. */ - if (mdlen < 20 || gcry_pkalgo == GCRY_PK_DSA) + if (mdlen < 20 || pkalgo == GCRY_PK_DSA) return gpg_error (GPG_ERR_INV_LENGTH); } diff --git a/g10/ChangeLog b/g10/ChangeLog index 0c8cbd4..75415f4 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,7 @@ +2011-01-21 Werner Koch + + * misc.c (openpgp_pk_algo_name): Always use the gcrypt function. + 2010-12-09 Werner Koch * tdbio.c (tdbio_set_dbname) [W32CE]: Take care of missing errno. diff --git a/g10/misc.c b/g10/misc.c index 6f77119..bdd797c 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -503,25 +503,7 @@ openpgp_pk_algo_usage ( int algo ) const char * openpgp_pk_algo_name (int algo) { - /* We use fixed strings to have pretty names instead of those from - libgcrypt. */ - switch (algo) - { - case PUBKEY_ALGO_RSA: - case PUBKEY_ALGO_RSA_E: - case PUBKEY_ALGO_RSA_S: return "rsa"; - - case PUBKEY_ALGO_ELGAMAL: - case PUBKEY_ALGO_ELGAMAL_E: return "elg"; - - case PUBKEY_ALGO_DSA: return "dsa"; - - case PUBKEY_ALGO_ECDSA:return "ecdsa"; - - case PUBKEY_ALGO_ECDH: return "ecdh"; - - default: gcry_pk_algo_name (map_pk_openpgp_to_gcry (algo)); - } + return gcry_pk_algo_name (map_pk_openpgp_to_gcry (algo)); } diff --git a/g10/sign.c b/g10/sign.c index 30dc66d..cbb3c62 100644 --- a/g10/sign.c +++ b/g10/sign.c @@ -298,6 +298,9 @@ do_sign (PKT_public_key *pksk, PKT_signature *sig, { PKT_public_key *pk = xmalloc_clear (sizeof *pk); + log_debug ("checking created signature algo=%d\n", mdalgo); + log_printhex ("md:", dp, gcry_md_get_algo_dlen (mdalgo)); + if (get_pubkey (pk, sig->keyid )) err = gpg_error (GPG_ERR_NO_PUBKEY); else diff --git a/include/ChangeLog b/include/ChangeLog index 7c1b372..8dd88ff 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,6 +1,6 @@ 2011-01-21 Werner Koch - * cipher.h (GCRY_PK_USAGE_CERT): Remove comaptibility macros + * cipher.h (GCRY_PK_USAGE_CERT): Remove compatibility macros because we now require libgcrypt 1.4.6. (GCRY_PK_ECDH): Add replacement. ----------------------------------------------------------------------- Summary of changes: agent/ChangeLog | 2 ++ agent/pksign.c | 33 ++++++++++++++++++--------------- g10/ChangeLog | 6 ++++++ g10/misc.c | 20 +------------------- g10/seskey.c | 10 ++++++---- include/ChangeLog | 2 +- 6 files changed, 34 insertions(+), 39 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jan 24 12:23:29 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 24 Jan 2011 12:23:29 +0100 Subject: [git] GnuPG - branch, ECC-INTEGRATION-2-1, updated. gnupg-2.1.0beta1-41-gb3adbb5 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, ECC-INTEGRATION-2-1 has been updated via b3adbb576e88a12ee9e7ea790a72ad5f1bff4c78 (commit) from c3db7705c049e31e678ff87e230b8160aa0027f1 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit b3adbb576e88a12ee9e7ea790a72ad5f1bff4c78 Author: Werner Koch Date: Mon Jan 24 12:02:35 2011 +0100 Fix regression introduced by "editing only change". Signing and verification using a new key works again. diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 5df336e..334a9a8 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -1953,7 +1953,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, else { /* Fill in public key parameters. */ - if (algorithm == PUBKEY_ALGO_ECDSA && algorithm == PUBKEY_ALGO_ECDH) + if (algorithm == PUBKEY_ALGO_ECDSA || algorithm == PUBKEY_ALGO_ECDH) { /* FIXME: The code in this function ignores the errors. */ byte name_oid[256]; ----------------------------------------------------------------------- Summary of changes: g10/parse-packet.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jan 24 12:46:40 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 24 Jan 2011 12:46:40 +0100 Subject: [git] GnuPG - branch, ECC-INTEGRATION-2-1, updated. gnupg-2.1.0beta1-57-gc5e8a4c Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, ECC-INTEGRATION-2-1 has been updated via c5e8a4c0fdde7f4aef2163a3710483c87bdf3161 (commit) via 62842cc7fe614e278638c008d0192d68a05a555a (commit) via 2b933ae8f6324115e1ede81996ab18fe2ac90715 (commit) via 49d25d3185636237b356781cdde7960f234f2d11 (commit) via 7f32d88ed1b81719e0cda11710fc66745deee6e2 (commit) via 13acd78a39750e3990684a5bb0951fe0db83fc5a (commit) via af500f0ae490bc4262419fa52bac62677e1672fa (commit) via 357f8d5398c2b481264641bfe21733869593edb8 (commit) via c2c5d30db8c0411afaaaeb1653096498894a38a8 (commit) via 260c41851ef72f4e039cfec2bdcecb93e818415e (commit) via dcd20e18a5b581d93e8259722d5f1b69d3af992b (commit) via 52b9761c8847523d35de3484e4b7fdefbb0e6a4e (commit) via 8db3bf8c47a76e9f7d75863d49c172b5ddd94896 (commit) via 300e16dd3828016fa60e35797679d7ee730ee7e0 (commit) via 8c8c45725f60b77adc367f72aa479bfa2f9b1ea2 (commit) via 2732f2ff3f44a5aae969d5ce16a4de74478576a2 (commit) from b3adbb576e88a12ee9e7ea790a72ad5f1bff4c78 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit c5e8a4c0fdde7f4aef2163a3710483c87bdf3161 Merge: b3adbb5 62842cc Author: Werner Koch Date: Mon Jan 24 12:24:11 2011 +0100 Merge branch 'master' into ECC-INTEGRATION-2-1 diff --cc ChangeLog index 287e4d1,11b37eb..d3e7eb1 --- a/ChangeLog +++ b/ChangeLog @@@ -1,8 -1,13 +1,18 @@@ + 2011-01-20 Werner Koch + + * configure.ac (AC_CONFIG_FILES): Remove keyserver/. + + 2011-01-19 Werner Koch + + * configure.ac: Add new option --enable-gpg2-is-gpg. + (NAME_OF_INSTALLED_GPG): New ac_define. + * autogen.sh [--build-w32ce]: Use --enable-gpg2-is-gpg. + +2011-01-21 Werner Koch + + * configure.ac: Need Libgcrypt 1.4.6 due to AESWRAP. + (HAVE_GCRY_PK_ECDH): Add new test. + 2011-01-03 Werner Koch * README.SVN: Rename to README.GIT. diff --cc agent/ChangeLog index 4b0712c,542695b..7dace3a --- a/agent/ChangeLog +++ b/agent/ChangeLog @@@ -1,9 -1,7 +1,13 @@@ + 2011-01-19 Werner Koch + + * trustlist.c (read_one_trustfile): Also chop an CR. + +2011-01-21 Werner Koch + + * pksign.c (do_encode_dsa): Compare MDLEN to bytes. + + * cvt-openpgp.c (GCRY_PK_ECDH) [!HAVE_GCRY_PK_ECDH]: New. + 2010-12-02 Werner Koch * gpg-agent.c (CHECK_OWN_SOCKET_INTERVAL) [W32CE]: Set to 60 diff --cc common/ChangeLog index 6a6f6e0,0150658..61f6b29 --- a/common/ChangeLog +++ b/common/ChangeLog @@@ -1,8 -1,55 +1,60 @@@ + 2011-01-20 Werner Koch + + Fix bug#1313. + + * http.c (my_select): New. Define to pth_select if building with Pth. + (start_server, write_server, cookie_read, cookie_write): Use it. + (my_connect): New. Define to pth_connect if building with Pth. + (connect_server): Use it. + (my_accept): New. Define to pth_accept if building with Pth. + (start_server): Use it. + + 2011-01-20 Werner Koch + + * util.h (struct b64state): Add field LASTERR. + * b64enc.c (enc_start, b64enc_write, b64enc_finish): Handle + LASTERR. This is to make sure that we don't leak strduped data. + * b64dec.c (b64dec_start, b64dec_proc, b64dec_finish): Ditto. + + * http.c (escape_data): New. + (insert_escapes): Implement using escape_data. + (http_escape_data): New. + + 2011-01-19 Werner Koch + + * homedir.c (gnupg_module_name): Use NAME_OF_INSTALLED_GPG instead + of "gpg2". + + 2011-01-18 Werner Koch + + * iobuf.c (file_es_filter_ctx_t): New. + (file_es_filter): New. + (iobuf_esopen): New. + + * membuf.c (clear_membuf, peek_membuf): New. + + * util.h (GPG_ERR_NO_KEYSERVER): New. + + * keyserver.h (keyserver_spec): Move from ../g10/options.h to here. + + * http.c (do_parse_uri): Add arg NO_SCHEME_CHECK. Change all + callers. Support HKP and HKPS. + (_http_parse_uri): Do proper error management. + * http.h (parsed_uri_s): Add field IS_HTTP. + (http_parse_uri): Support NO_SCHEME_CHECK arg. + + * estream.c (es_func_mem_write): Fix computation of NEWSIZE. + + 2011-01-10 Werner Koch + + * session-env.c (update_var): Fix same value detection. Fixes + bug#1311. + +2011-01-10 Werner Koch + + * session-env.c (update_var): Fix same value detection. Fixes + bug#1311. + 2010-12-17 Werner Koch * asshelp.c (lock_spawning): Add arg VERBOSE. Improve timeout diff --cc g10/ChangeLog index 8e79587,a60d5d5..4c28363 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@@ -1,9 -1,25 +1,31 @@@ + 2011-01-20 Werner Koch + + * keyserver.c: Rewrite most stuff for use with dirmngr. Get rid + of all spawn code. Work work pending. + + * export.c (export_pubkeys_buffer): New. + + * import.c (import_keys_es_stream): New. + + * call-dirmngr.c, call-dirmngr.h: New. + * gpg.h (server_control_s): Add DIRMNGR_LOCAL. + * gpg.c: Include call-dirmngr.h. + (gpg_deinit_default_ctrl): Call gpg_dirmngr_deinit_session_data. + + 2011-01-06 Werner Koch + + * gpg.c (main): Use keyserver_spec_t. + + * options.h (struct opt): Factor definition of struct keyserver + out to ../common/keyserver.h. + (keyserver_spec_t): New. + +2011-01-21 Werner Koch + + * seskey.c (encode_md_value): Truncate the DSA hash again. + + * misc.c (openpgp_pk_algo_name): Always use the gcrypt function. + 2010-12-09 Werner Koch * tdbio.c (tdbio_set_dbname) [W32CE]: Take care of missing errno. ----------------------------------------------------------------------- Summary of changes: ChangeLog | 12 +- Makefile.am | 2 +- NEWS | 3 + agent/ChangeLog | 4 + agent/trustlist.c | 9 +- autogen.sh | 3 +- common/ChangeLog | 52 + common/b64dec.c | 32 +- common/b64enc.c | 22 +- common/estream.c | 2 +- common/homedir.c | 2 +- common/http.c | 121 ++- common/http.h | 15 +- common/iobuf.c | 127 +++- common/iobuf.h | 2 + common/keyserver.h | 24 +- common/membuf.c | 45 +- common/membuf.h | 3 +- common/util.h | 4 + configure.ac | 26 +- dirmngr/ChangeLog | 20 +- dirmngr/Makefile.am | 3 +- dirmngr/crlfetch.c | 4 +- dirmngr/dirmngr.c | 58 +- dirmngr/dirmngr.h | 14 +- dirmngr/ks-action.c | 183 ++++ common/userids.h => dirmngr/ks-action.h | 16 +- dirmngr/ks-engine-hkp.c | 558 +++++++++++ g13/be-truecrypt.h => dirmngr/ks-engine.h | 21 +- dirmngr/server.c | 285 ++++++- doc/debugging.texi | 4 +- doc/gnupg.texi | 8 +- doc/tools.texi | 5 +- g10/ChangeLog | 24 +- g10/Makefile.am | 1 + g10/call-dirmngr.c | 611 ++++++++++++ common/init.h => g10/call-dirmngr.h | 18 +- g10/export.c | 54 ++ g10/gpg.c | 45 +- g10/gpg.h | 8 + g10/import.c | 26 + g10/keyserver-internal.h | 2 +- g10/keyserver.c | 1438 +++++++++++------------------ g10/main.h | 7 + g10/options.h | 28 +- keyserver/ChangeLog | 6 + keyserver/gpgkeys_hkp.c | 5 +- po/ChangeLog | 4 + po/de.po | 1158 ++++++++++++------------ 49 files changed, 3474 insertions(+), 1650 deletions(-) create mode 100644 dirmngr/ks-action.c copy common/userids.h => dirmngr/ks-action.h (61%) create mode 100644 dirmngr/ks-engine-hkp.c copy g13/be-truecrypt.h => dirmngr/ks-engine.h (51%) create mode 100644 g10/call-dirmngr.c copy common/init.h => g10/call-dirmngr.h (50%) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jan 24 16:10:40 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 24 Jan 2011 16:10:40 +0100 Subject: [git] GnuPG - branch, ECC-INTEGRATION-2-1, updated. gnupg-2.1.0beta1-58-ge9d9e96 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, ECC-INTEGRATION-2-1 has been updated via e9d9e96d8ba464a1652552c33636819eed1e9f9a (commit) from c5e8a4c0fdde7f4aef2163a3710483c87bdf3161 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit e9d9e96d8ba464a1652552c33636819eed1e9f9a Author: Werner Koch Date: Mon Jan 24 15:50:37 2011 +0100 Fix ECDH configure test diff --git a/common/ChangeLog b/common/ChangeLog index 61f6b29..0150658 100644 --- a/common/ChangeLog +++ b/common/ChangeLog @@ -50,11 +50,6 @@ * session-env.c (update_var): Fix same value detection. Fixes bug#1311. -2011-01-10 Werner Koch - - * session-env.c (update_var): Fix same value detection. Fixes - bug#1311. - 2010-12-17 Werner Koch * asshelp.c (lock_spawning): Add arg VERBOSE. Improve timeout diff --git a/configure.ac b/configure.ac index a944e80..e24117b 100644 --- a/configure.ac +++ b/configure.ac @@ -746,7 +746,7 @@ AC_CACHE_CHECK([whether Libgcrypt support ECDH], gnupg_cv_gcry_pk_ecdh, [ _gnupg_gcry_save_cflags=$CFLAGS CFLAGS="$CFLAGS $LIBGCRYPT_CFLAGS" AC_TRY_COMPILE( - [#include ], + [#include ], [ return GCRY_PK_ECDH; ], gnupg_cv_gcry_pk_ecdh=yes, gnupg_cv_gcry_pk_ecdh=no) ----------------------------------------------------------------------- Summary of changes: common/ChangeLog | 5 ----- configure.ac | 2 +- 2 files changed, 1 insertions(+), 6 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jan 24 18:44:52 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 24 Jan 2011 18:44:52 +0100 Subject: [git] GnuPG - branch, ECC-INTEGRATION-2-1, updated. gnupg-2.1.0beta1-59-gb9958bb Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, ECC-INTEGRATION-2-1 has been updated via b9958bba10f40a348d40c173701d15cb6b0a7f66 (commit) from e9d9e96d8ba464a1652552c33636819eed1e9f9a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit b9958bba10f40a348d40c173701d15cb6b0a7f66 Author: Werner Koch Date: Mon Jan 24 18:16:03 2011 +0100 Fix another stupid bug ECDH detection bug Again reported by Johan van Selst. Let's see whether this one is okay. diff --git a/include/cipher.h b/include/cipher.h index 03d38da..3110208 100644 --- a/include/cipher.h +++ b/include/cipher.h @@ -23,7 +23,7 @@ #include /* Macros for compatibility with older libgcrypt versions. */ -#ifndef HAVE_GCRY_PK_ECDSA +#ifndef HAVE_GCRY_PK_ECDH # define GCRY_PK_ECDH 302 #endif ----------------------------------------------------------------------- Summary of changes: include/cipher.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Tue Jan 25 11:47:53 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 25 Jan 2011 11:47:53 +0100 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta1-46-g2b81258 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, master has been updated via 2b81258b2bf80e4819904028c3ac5fddcec2a8e9 (commit) from 62842cc7fe614e278638c008d0192d68a05a555a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 2b81258b2bf80e4819904028c3ac5fddcec2a8e9 Author: Werner Koch Date: Tue Jan 25 11:26:01 2011 +0100 Make dirmngr more battery friendly. Similar to gpg-agent, dirmngr's wait timeouts are now synced to the full second. Increased ldap helper thread timeout to 2 seconds. Nuked some white spaces. diff --git a/dirmngr/ChangeLog b/dirmngr/ChangeLog index 39df05d..716effb 100644 --- a/dirmngr/ChangeLog +++ b/dirmngr/ChangeLog @@ -1,3 +1,11 @@ +2011-01-25 Werner Koch + + * dirmngr.c (handle_connections): Rewrite loop to use pth-select + so to sync timeouts to the full second. + (pth_thread_id): New. + * ldap-wrapper.c (ldap_wrapper_thread): Sync to the full second. + Increate pth_wait timeout from 1 to 2 seconds. + 2011-01-20 Werner Koch * server.c (release_ctrl_keyservers): New. diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c index ae922fa..678cf3d 100644 --- a/dirmngr/dirmngr.c +++ b/dirmngr/dirmngr.c @@ -1,6 +1,6 @@ /* dirmngr.c - LDAP access * Copyright (C) 2002 Klar?lvdalens Datakonsult AB - * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2010 g10 Code GmbH + * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2010, 2011 g10 Code GmbH * * This file is part of DirMngr. * @@ -47,7 +47,7 @@ #define JNLIB_NEED_AFLOCAL #include "dirmngr.h" -#include +#include #include "certcache.h" #include "crlcache.h" @@ -74,7 +74,7 @@ enum cmd_and_opt_values { oSh = 's', oVerbose = 'v', oNoVerbose = 500, - + aServer, aDaemon, aService, @@ -128,7 +128,7 @@ enum cmd_and_opt_values { static ARGPARSE_OPTS opts[] = { - + ARGPARSE_group (300, N_("@Commands:\n ")), ARGPARSE_c (aServer, "server", N_("run in server mode (foreground)") ), @@ -185,13 +185,13 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_s (oOCSPResponder, "ocsp-responder", N_("|URL|use OCSP responder at URL")), - ARGPARSE_s_s (oOCSPSigner, "ocsp-signer", - N_("|FPR|OCSP response signed by FPR")), + ARGPARSE_s_s (oOCSPSigner, "ocsp-signer", + N_("|FPR|OCSP response signed by FPR")), ARGPARSE_s_i (oOCSPMaxClockSkew, "ocsp-max-clock-skew", "@"), ARGPARSE_s_i (oOCSPMaxPeriod, "ocsp-max-period", "@"), ARGPARSE_s_i (oOCSPCurrentPeriod, "ocsp-current-period", "@"), - ARGPARSE_s_i (oMaxReplies, "max-replies", + ARGPARSE_s_i (oMaxReplies, "max-replies", N_("|N|do not return more than N items in one query")), ARGPARSE_s_s (oSocketName, "socket-name", "@"), /* Only for debugging. */ @@ -201,7 +201,7 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_n (oDebugAll, "debug-all", "@"), ARGPARSE_s_i (oDebugWait, "debug-wait", "@"), ARGPARSE_s_n (oNoGreeting, "no-greeting", "@"), - ARGPARSE_s_s (oHomedir, "homedir", "@"), + ARGPARSE_s_s (oHomedir, "homedir", "@"), ARGPARSE_s_s (oLDAPWrapperProgram, "ldap-wrapper-program", "@"), ARGPARSE_s_s (oHTTPWrapperProgram, "http-wrapper-program", "@"), ARGPARSE_s_n (oHonorHTTPProxy, "honor-http-proxy", "@"), @@ -286,11 +286,18 @@ static int fixed_gcry_pth_init (void) return pth_self ()? 0 : (pth_init () == FALSE) ? errno : 0; } +#ifndef PTH_HAVE_PTH_THREAD_ID +static unsigned long pth_thread_id (void) +{ + return (unsigned long)pth_self (); +} +#endif + static const char * my_strusage( int level ) { const char *p; - switch ( level ) + switch ( level ) { case 11: p = "dirmngr (GnuPG)"; break; @@ -307,7 +314,7 @@ my_strusage( int level ) case 41: p = _("Syntax: dirmngr [options] [command [args]]\n" "LDAP and OCSP access for GnuPG\n"); break; - + default: p = NULL; } return p; @@ -318,18 +325,18 @@ my_strusage( int level ) implementation does only allow SHA-1 for hashing. This may be extended by mapping the name, testing for algorithm availibility and adjust the length checks accordingly. */ -static gpg_error_t +static gpg_error_t my_ksba_hash_buffer (void *arg, const char *oid, const void *buffer, size_t length, size_t resultsize, unsigned char *result, size_t *resultlen) { (void)arg; - if (oid && strcmp (oid, "1.3.14.3.2.26")) - return gpg_error (GPG_ERR_NOT_SUPPORTED); + if (oid && strcmp (oid, "1.3.14.3.2.26")) + return gpg_error (GPG_ERR_NOT_SUPPORTED); if (resultsize < 20) return gpg_error (GPG_ERR_BUFFER_TOO_SHORT); - gcry_md_hash_buffer (2, result, buffer, length); + gcry_md_hash_buffer (2, result, buffer, length); *resultlen = 20; return 0; } @@ -362,7 +369,7 @@ set_debug (void) /* Unless the "guru" string has been used we don't want to allow hashing debugging. The rationale is that people tend to select the highest debug value and would then clutter their - disk with debug files which may reveal confidential data. */ + disk with debug files which may reveal confidential data. */ if (numok) opt.debug &= ~(DBG_HASHING_VALUE); } @@ -387,7 +394,7 @@ set_debug (void) if (opt.debug & DBG_CRYPTO_VALUE ) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1); } - + static void wrong_args (const char *text) @@ -422,10 +429,10 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) opt.debug = 0; opt.ldap_wrapper_program = NULL; opt.disable_http = 0; - opt.disable_ldap = 0; - opt.honor_http_proxy = 0; - opt.http_proxy = NULL; - opt.ldap_proxy = NULL; + opt.disable_ldap = 0; + opt.honor_http_proxy = 0; + opt.http_proxy = NULL; + opt.ldap_proxy = NULL; opt.only_ldap_proxy = 0; opt.ignore_http_dp = 0; opt.ignore_ldap_dp = 0; @@ -485,7 +492,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) case oAllowOCSP: opt.allow_ocsp = 1; break; case oOCSPResponder: opt.ocsp_responder = pargs->r.ret_str; break; - case oOCSPSigner: + case oOCSPSigner: opt.ocsp_signer = parse_ocsp_signer (pargs->r.ret_str); break; case oOCSPMaxClockSkew: opt.ocsp_max_clock_skew = pargs->r.ret_int; break; @@ -521,13 +528,13 @@ w32_service_control (DWORD control, DWORD event_type, LPVOID event_data, case SERVICE_CONTROL_SHUTDOWN: /* For shutdown we will try to force termination. */ service_status.dwCurrentState = SERVICE_STOP_PENDING; - SetServiceStatus (service_handle, &service_status); + SetServiceStatus (service_handle, &service_status); shutdown_pending = 3; break; case SERVICE_CONTROL_STOP: service_status.dwCurrentState = SERVICE_STOP_PENDING; - SetServiceStatus (service_handle, &service_status); + SetServiceStatus (service_handle, &service_status); shutdown_pending = 1; break; @@ -600,12 +607,12 @@ main (int argc, char **argv) service_status.dwServiceSpecificExitCode = NO_ERROR; service_status.dwCheckPoint = 0; service_status.dwWaitHint = 10000; /* 10 seconds timeout. */ - SetServiceStatus (service_handle, &service_status); + SetServiceStatus (service_handle, &service_status); } #endif /*USE_W32_SERVICE*/ set_strusage (my_strusage); - log_set_prefix ("dirmngr", 1|4); + log_set_prefix ("dirmngr", 1|4); /* Make sure that our subsystems are ready. */ i18n_init (); @@ -621,7 +628,7 @@ main (int argc, char **argv) gpg_strerror (rc)); } gcry_control (GCRYCTL_DISABLE_SECMEM, 0); - + /* Check that the libraries are suitable. Do it here because the option parsing may need services of the libraries. */ @@ -664,9 +671,9 @@ main (int argc, char **argv) if (pth_key_setdata (my_tlskey_current_fd, NULL)) log_set_pid_suffix_cb (pid_suffix_callback); #endif /*!HAVE_W32_SYSTEM*/ - + /* Reset rereadable options to default values. */ - parse_rereadable_options (NULL, 0); + parse_rereadable_options (NULL, 0); /* LDAP defaults. */ opt.add_new_ldapservers = 0; @@ -732,7 +739,7 @@ main (int argc, char **argv) if (default_config) configname = make_filename (opt.homedir, "dirmngr.conf", NULL ); - + argc = orig_argc; argv = orig_argv; pargs.argc = &argc; @@ -757,7 +764,7 @@ main (int argc, char **argv) configname, strerror(errno) ); exit(2); } - xfree (configname); + xfree (configname); configname = NULL; } if (parse_debug && configname ) @@ -771,13 +778,13 @@ main (int argc, char **argv) continue; /* Already handled */ switch (pargs.r_opt) { - case aServer: + case aServer: case aDaemon: case aService: - case aShutdown: - case aFlush: - case aListCRLs: - case aLoadCRL: + case aShutdown: + case aFlush: + case aListCRLs: + case aLoadCRL: case aFetchCRL: case aGPGConfList: case aGPGConfTest: @@ -812,8 +819,8 @@ main (int argc, char **argv) case oSh: csh_style = 0; break; case oLDAPFile: ldapfile = pargs.r.ret_str; break; case oLDAPAddServers: opt.add_new_ldapservers = 1; break; - case oLDAPTimeout: - opt.ldaptimeout = pargs.r.ret_int; + case oLDAPTimeout: + opt.ldaptimeout = pargs.r.ret_int; break; case oFakedSystemTime: @@ -860,12 +867,12 @@ main (int argc, char **argv) #endif if (!access ("/etc/dirmngr", F_OK) && !strncmp (opt.homedir, "/etc/", 5)) - log_info + log_info ("NOTE: DirMngr is now a proper part of GnuPG. The configuration and" " other directory names changed. Please check that no other version" " of dirmngr is still installed. To disable this warning, remove the" " directory `/etc/dirmngr'.\n"); - + if (gnupg_faked_time_p ()) { gnupg_isotime_t tbuf; @@ -879,7 +886,7 @@ main (int argc, char **argv) set_debug (); /* Get LDAP server list from file. */ - if (!ldapfile) + if (!ldapfile) { ldapfile = make_filename (opt.homedir, opt.system_daemon? @@ -917,7 +924,7 @@ main (int argc, char **argv) log_set_file (logfile); log_set_prefix (NULL, 2|4); } - + if (debug_wait) { log_debug ("waiting for debugger - my pid is %u .....\n", @@ -941,7 +948,7 @@ main (int argc, char **argv) if (argc) wrong_args ("--daemon"); - + /* Now start with logging to a file if this is desired. */ if (logfile) { @@ -959,12 +966,12 @@ main (int argc, char **argv) dirmngr_exit (1); } #endif - if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path ) + if (strlen (socket_name)+1 >= sizeof serv_addr.sun_path ) { log_error (_("name of socket too long\n")); dirmngr_exit (1); } - + fd = assuan_sock_new (AF_UNIX, SOCK_STREAM, 0); if (fd == ASSUAN_INVALID_FD) { @@ -979,7 +986,7 @@ main (int argc, char **argv) len = SUN_LEN (&serv_addr); rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len); - if (rc == -1 + if (rc == -1 && (errno == EADDRINUSE #ifdef HAVE_W32_SYSTEM || errno == EEXIST @@ -990,7 +997,7 @@ main (int argc, char **argv) gnupg_remove (socket_name); rc = assuan_sock_bind (fd, (struct sockaddr*) &serv_addr, len); } - if (rc != -1 + if (rc != -1 && (rc = assuan_sock_get_nonce ((struct sockaddr*) &serv_addr, len, &socket_nonce))) log_error (_("error getting nonce for the socket\n")); if (rc == -1) @@ -1001,7 +1008,7 @@ main (int argc, char **argv) dirmngr_exit (1); } cleanup_socket = 1; - + if (listen (FD2INT (fd), 5) == -1) { log_error (_("listen() failed: %s\n"), strerror (errno)); @@ -1022,22 +1029,22 @@ main (int argc, char **argv) es_printf ("set DIRMNGR_INFO=%s;%lu;1\n", socket_name, (ulong) pid); #else pid = pth_fork (); - if (pid == (pid_t)-1) + if (pid == (pid_t)-1) { log_fatal (_("error forking process: %s\n"), strerror (errno)); dirmngr_exit (1); } - if (pid) + if (pid) { /* We are the parent */ char *infostr; - + /* Don't let cleanup() remove the socket - the child is responsible for doing that. */ cleanup_socket = 0; close (fd); - + /* Create the info string: :: */ if (asprintf (&infostr, "DIRMNGR_INFO=%s:%lu:1", socket_name, (ulong)pid ) < 0) @@ -1058,18 +1065,18 @@ main (int argc, char **argv) es_printf ( "%s; export DIRMNGR_INFO;\n", infostr); } free (infostr); - exit (0); + exit (0); /*NEVER REACHED*/ } /* end parent */ - - - /* + + + /* This is the child */ /* Detach from tty and put process into a new session */ if (!nodetach ) - { + { int i; unsigned int oldflags; @@ -1165,7 +1172,7 @@ main (int argc, char **argv) argv[0], gpg_strerror (rc)); else { - rc = crl_cache_insert (&ctrlbuf, argv[0], reader); + rc = crl_cache_insert (&ctrlbuf, argv[0], reader); if (rc) log_error (_("processing CRL from `%s' failed: %s\n"), argv[0], gpg_strerror (rc)); @@ -1236,7 +1243,7 @@ main (int argc, char **argv) and having both of them is thus problematic. --no-detach is also only usable on the command line. --batch is unused. */ - filename = make_filename (opt.homedir, + filename = make_filename (opt.homedir, opt.system_daemon? "ldapservers.conf":"dirmngr_ldapservers.conf", NULL); @@ -1327,7 +1334,7 @@ cleanup (void) } -void +void dirmngr_exit (int rc) { cleanup (); @@ -1345,7 +1352,7 @@ dirmngr_init_default_ctrl (ctrl_t ctrl) /* Create a list of LDAP servers from the file FILENAME. Returns the - list or NULL in case of errors. + list or NULL in case of errors. The format fo such a file is line oriented where empty lines and lines starting with a hash mark are ignored. All other lines are @@ -1353,7 +1360,7 @@ dirmngr_init_default_ctrl (ctrl_t ctrl) 1. field: Hostname 2. field: Portnumber - 3. field: Username + 3. field: Username 4. field: Password 5. field: Base DN @@ -1406,8 +1413,8 @@ parse_ldapserver_file (const char* filename) *serverend = server; serverend = &server->next; } - } - + } + if (es_ferror (fp)) log_error (_("error reading `%s': %s\n"), filename, strerror (errno)); es_fclose (fp); @@ -1441,14 +1448,14 @@ parse_ocsp_signer (const char *string) item->hexfpr[j] = 0; if (j != 40 || !(spacep (string+i) || !string[i])) { - log_error (_("%s:%u: invalid fingerprint detected\n"), + log_error (_("%s:%u: invalid fingerprint detected\n"), "--ocsp-signer", 0); xfree (item); return NULL; } return item; } - + /* Well, it is a filename. */ if (*string == '/' || (*string == '~' && string[1] == '/')) fname = make_filename (string, NULL); @@ -1503,7 +1510,7 @@ parse_ocsp_signer (const char *string) ; err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG /* */: GPG_ERR_INCOMPLETE_LINE); - log_error (_("%s:%u: read error: %s\n"), + log_error (_("%s:%u: read error: %s\n"), fname, lnr, gpg_strerror (err)); errflag = 1; continue; @@ -1541,14 +1548,14 @@ parse_ocsp_signer (const char *string) /* - Stuff used in daemon mode. + Stuff used in daemon mode. */ /* Reread parts of the configuration. Note, that this function is obviously not thread-safe and should only be called from the PTH - signal handler. + signal handler. Fixme: Due to the way the argument parsing works, we create a memory leak here for all string type arguments. There is currently @@ -1619,11 +1626,11 @@ handle_signal (int signo) case SIGHUP: dirmngr_sighup_action (); break; - + case SIGUSR1: cert_cache_print_stats (); break; - + case SIGUSR2: log_info (_("SIGUSR2 received - no action defined\n")); break; @@ -1643,7 +1650,7 @@ handle_signal (int signo) dirmngr_exit (0); } break; - + case SIGINT: log_info (_("SIGINT received - immediate shutdown\n")); log_info( "%s %s stopped\n", strusage(11), strusage(13)); @@ -1681,12 +1688,12 @@ handle_tick (void) /* Check the nonce on a new connection. This is a NOP unless we we are using our Unix domain socket emulation under Windows. */ -static int +static int check_nonce (assuan_fd_t fd, assuan_sock_nonce_t *nonce) { if (assuan_sock_check_nonce (fd, nonce)) { - log_info (_("error reading nonce on fd %d: %s\n"), + log_info (_("error reading nonce on fd %d: %s\n"), FD2INT (fd), strerror (errno)); assuan_sock_close (fd); return -1; @@ -1701,13 +1708,16 @@ static void * start_connection_thread (void *arg) { union int_and_ptr_u argval; - assuan_fd_t fd; + gnupg_fd_t fd; argval.aptr = arg; fd = argval.afd; if (check_nonce (fd, &socket_nonce)) - return NULL; + { + log_error ("handler 0x%lx nonce check FAILED\n", pth_thread_id ()); + return NULL; + } #ifndef HAVE_W32_SYSTEM pth_key_setdata (my_tlskey_current_fd, argval.aptr); @@ -1727,7 +1737,7 @@ start_connection_thread (void *arg) argval.afd = ASSUAN_INVALID_FD; pth_key_setdata (my_tlskey_current_fd, argval.aptr); #endif - + return NULL; } @@ -1738,11 +1748,13 @@ handle_connections (assuan_fd_t listen_fd) { pth_attr_t tattr; pth_event_t ev, time_ev; - sigset_t sigs, oldsigs; + sigset_t sigs; int signo; struct sockaddr_un paddr; socklen_t plen = sizeof( paddr ); - assuan_fd_t fd; + gnupg_fd_t fd; + int nfd, ret; + fd_set fdset, read_fdset; tattr = pth_attr_new(); pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0); @@ -1750,46 +1762,89 @@ handle_connections (assuan_fd_t listen_fd) pth_attr_set (tattr, PTH_ATTR_NAME, "dirmngr"); #ifndef HAVE_W32_SYSTEM /* FIXME */ + /* Make sure that the signals we are going to handle are not blocked + and create an event object for them. We also set the default + action to ignore because we use an Pth event to get notified + about signals. This avoids that the default action is taken in + case soemthing goes wrong within Pth. The problem might also be + a Pth bug. */ sigemptyset (&sigs ); - sigaddset (&sigs, SIGHUP); - sigaddset (&sigs, SIGUSR1); - sigaddset (&sigs, SIGUSR2); - sigaddset (&sigs, SIGINT); - sigaddset (&sigs, SIGTERM); + { + static const int mysigs[] = { SIGHUP, SIGUSR1, SIGUSR2, SIGINT, SIGTERM }; + struct sigaction sa; + int i; + + for (i=0; i < DIM (mysigs); i++) + { + sigemptyset (&sa.sa_mask); + sa.sa_handler = SIG_IGN; + sa.sa_flags = 0; + sigaction (mysigs[i], &sa, NULL); + + sigaddset (&sigs, mysigs[i]); + } + } + + pth_sigmask (SIG_UNBLOCK, &sigs, NULL); ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo); #else + /* Use a dummy event. */ sigs = 0; ev = pth_event (PTH_EVENT_SIGS, &sigs, &signo); #endif time_ev = NULL; + /* Setup the fdset. It has only one member. This is because we use + pth_select instead of pth_accept to properly sync timeouts with + to full second. */ + FD_ZERO (&fdset); + FD_SET (FD2INT (listen_fd), &fdset); + nfd = FD2INT (listen_fd); + + /* Main loop. */ for (;;) { + /* Make sure that our signals are not blocked. */ + pth_sigmask (SIG_UNBLOCK, &sigs, NULL); + + /* Shutdown test. */ if (shutdown_pending) { if (!active_connections) break; /* ready */ - /* Do not accept anymore connections but wait for existing - connections to terminate. */ - signo = 0; - pth_wait (ev); - if (pth_event_occurred (ev) && signo) - handle_signal (signo); - continue; + /* Do not accept new connections but keep on running the + loop to cope with the timer events. */ + FD_ZERO (&fdset); } + /* Create a timeout event if needed. To help with power saving + we syncronize the ticks to the next full second. */ if (!time_ev) - time_ev = pth_event (PTH_EVENT_TIME, - pth_timeout (TIMERTICK_INTERVAL, 0)); + { + pth_time_t nexttick; + + nexttick = pth_timeout (TIMERTICK_INTERVAL, 0); + if (nexttick.tv_usec > 10) /* Use a 10 usec threshhold. */ + { + nexttick.tv_sec++; + nexttick.tv_usec = 0; + } + time_ev = pth_event (PTH_EVENT_TIME, nexttick); + } + + /* Take a copy of the fdset. */ + read_fdset = fdset; if (time_ev) pth_event_concat (ev, time_ev, NULL); - fd = (assuan_fd_t) pth_accept_ev (FD2INT (listen_fd), (struct sockaddr *)&paddr, &plen, ev); + + ret = pth_select_ev (nfd+1, &read_fdset, NULL, NULL, NULL, ev); + if (time_ev) pth_event_isolate (time_ev); - if (fd == ASSUAN_INVALID_FD) + if (ret == -1) { if (pth_event_occurred (ev) || (time_ev && pth_event_occurred (time_ev)) ) @@ -1804,7 +1859,8 @@ handle_connections (assuan_fd_t listen_fd) } continue; } - log_error (_("accept failed: %s - waiting 1s\n"), strerror (errno)); + log_error (_("pth_select failed: %s - waiting 1s\n"), + strerror (errno)); pth_sleep (1); continue; } @@ -1825,25 +1881,38 @@ handle_connections (assuan_fd_t listen_fd) /* We now might create a new thread and because we don't want any signals (as we are handling them here) to be delivered to a new thread we need to block those signals. */ - pth_sigmask (SIG_BLOCK, &sigs, &oldsigs); - - /* Create thread to handle this connection. */ - { - union int_and_ptr_u argval; - - argval.afd = fd; - if (!pth_spawn (tattr, start_connection_thread, argval.aptr)) - { - log_error (_("error spawning connection handler: %s\n"), - strerror (errno) ); - assuan_sock_close (fd); - } - } + pth_sigmask (SIG_BLOCK, &sigs, NULL); - /* Restore the signal mask. */ - pth_sigmask (SIG_SETMASK, &oldsigs, NULL); + if (!shutdown_pending && FD_ISSET (FD2INT (listen_fd), &read_fdset)) + { + plen = sizeof paddr; + fd = INT2FD (pth_accept (FD2INT(listen_fd), + (struct sockaddr *)&paddr, &plen)); + if (fd == GNUPG_INVALID_FD) + { + log_error ("accept failed: %s\n", strerror (errno)); + } + else + { + char threadname[50]; + union int_and_ptr_u argval; + + argval.afd = fd; + snprintf (threadname, sizeof threadname-1, + "conn fd=%d", FD2INT(fd)); + threadname[sizeof threadname -1] = 0; + pth_attr_set (tattr, PTH_ATTR_NAME, threadname); + if (!pth_spawn (tattr, start_connection_thread, argval.aptr)) + { + log_error ("error spawning connection handler: %s\n", + strerror (errno) ); + assuan_sock_close (fd); + } + } + fd = GNUPG_INVALID_FD; + } } - + pth_event_free (ev, PTH_FREE_ALL); if (time_ev) pth_event_free (time_ev, PTH_FREE_ALL); diff --git a/dirmngr/ldap-wrapper.c b/dirmngr/ldap-wrapper.c index 25ec155..fa5bf3c 100644 --- a/dirmngr/ldap-wrapper.c +++ b/dirmngr/ldap-wrapper.c @@ -269,8 +269,17 @@ ldap_wrapper_thread (void *dummy) { pth_event_t timeout_ev; int any_action = 0; + pth_time_t nexttick; - timeout_ev = pth_event (PTH_EVENT_TIME, pth_timeout (1, 0)); + /* We timeout the pth_wait every 2 seconds. To help with power + saving we syncronize the timeouts to the next full second. */ + nexttick = pth_timeout (2, 0); + if (nexttick.tv_usec > 10) /* Use a 10 usec threshhold. */ + { + nexttick.tv_sec++; + nexttick.tv_usec = 0; + } + timeout_ev = pth_event (PTH_EVENT_TIME, nexttick); if (! timeout_ev) { log_error (_("pth_event failed: %s\n"), strerror (errno)); diff --git a/po/remove-potcdate.sed b/po/remove-potcdate.sed deleted file mode 100644 index edb38d7..0000000 --- a/po/remove-potcdate.sed +++ /dev/null @@ -1,11 +0,0 @@ -/^"POT-Creation-Date: .*"$/{ -x -s/P/P/ -ta -g -d -bb -:a -x -:b -} ----------------------------------------------------------------------- Summary of changes: dirmngr/ChangeLog | 8 ++ dirmngr/dirmngr.c | 293 +++++++++++++++++++++++++++++------------------ dirmngr/ldap-wrapper.c | 11 ++- po/remove-potcdate.sed | 11 -- 4 files changed, 199 insertions(+), 124 deletions(-) delete mode 100644 po/remove-potcdate.sed hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Tue Jan 25 14:06:05 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 25 Jan 2011 14:06:05 +0100 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta1-47-g05a3f56 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, master has been updated via 05a3f5639139c14d360da29141108a868fbc3071 (commit) from 2b81258b2bf80e4819904028c3ac5fddcec2a8e9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 05a3f5639139c14d360da29141108a868fbc3071 Author: Werner Koch Date: Tue Jan 25 13:44:27 2011 +0100 Fix setting of default homedir for Wince Accidentally used == for assignment. Not a problem in our test environment because we use /gnupg as home directory anyway. diff --git a/dirmngr/ChangeLog b/dirmngr/ChangeLog index 716effb..02defce 100644 --- a/dirmngr/ChangeLog +++ b/dirmngr/ChangeLog @@ -3,6 +3,8 @@ * dirmngr.c (handle_connections): Rewrite loop to use pth-select so to sync timeouts to the full second. (pth_thread_id): New. + (main) [W32CE]: Fix setting of default homedir. + * ldap-wrapper.c (ldap_wrapper_thread): Sync to the full second. Increate pth_wait timeout from 1 to 2 seconds. diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c index 678cf3d..e1bae7e 100644 --- a/dirmngr/dirmngr.c +++ b/dirmngr/dirmngr.c @@ -729,7 +729,7 @@ main (int argc, char **argv) if (opt.system_daemon && !homedir_seen) { #ifdef HAVE_W32CE_SYSTEM - opt.homedir == DIRSEP_S "gnupg"; + opt.homedir = DIRSEP_S "gnupg"; #else opt.homedir = gnupg_sysconfdir (); #endif ----------------------------------------------------------------------- Summary of changes: dirmngr/ChangeLog | 2 ++ dirmngr/dirmngr.c | 2 +- 2 files changed, 3 insertions(+), 1 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Tue Jan 25 20:52:18 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 25 Jan 2011 20:52:18 +0100 Subject: [git] GnuPG - branch, ECC-INTEGRATION-2-1, updated. gnupg-2.1.0beta1-62-gd879c28 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, ECC-INTEGRATION-2-1 has been updated via d879c287ac1da7990c97b911018d63410c60433c (commit) via 302c5a826c0fd0b2aab85ad3c287b65429db2066 (commit) via 638dca5dbc7e119ff5a05dbdb109fbc171624605 (commit) from b9958bba10f40a348d40c173701d15cb6b0a7f66 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit d879c287ac1da7990c97b911018d63410c60433c Author: Werner Koch Date: Tue Jan 25 20:28:25 2011 +0100 Started with some code cleanups in ECDH. The goal is to have the ECDH code more uniform with the other algorithms. Also make error messages and variable names more similar to other places. diff --git a/g10/ChangeLog b/g10/ChangeLog index 3ce4d1f..9e1aa01 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -3,6 +3,9 @@ * ecdh.c (pk_ecdh_default_params_to_mpi): Remove. (pk_ecdh_default_params): Rewrite. Factor KEK table out to .. (kek_params_table): .. here. + (pk_ecdh_generate_ephemeral_key): New. + (pk_ecdh_encrypt): Remove. + (pk_ecdh_encrypt_with_shared_point): Make public. * pubkey-enc.c (get_it): Fix assertion. Use GPG_ERR_WRONG_SECKEY instead of log_fatal. Add safety checks diff --git a/g10/ecdh.c b/g10/ecdh.c index 1fa36aa..71c32fd 100644 --- a/g10/ecdh.c +++ b/g10/ecdh.c @@ -87,20 +87,26 @@ pk_ecdh_default_params (unsigned int qbits, size_t *sizeout) } -/* Encrypts/decrypts 'data' with a key derived from shared_mpi ECC - * point using FIPS SP 800-56A compliant method, which is key - * derivation + key wrapping. The direction is determined by the first - * parameter (is_encrypt=1 --> this is encryption). The result is - * returned in out as a size+value MPI. - * - * TODO: memory leaks (x_secret). +/* Encrypts/decrypts DATA using a key derived from the ECC shared + point SHARED_MPI using the FIPS SP 800-56A compliant method + 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. + + FIXME: explain PKEY and PK_FP. */ -static int + +/* + TODO: memory leaks (x_secret). +*/ +gpg_error_t 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 *out) + gcry_mpi_t *r_result) { + gpg_error_t err; byte *secret_x; int secret_x_size; byte kdf_params[256]; @@ -108,47 +114,54 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, int nbits; int kdf_hash_algo; int kdf_encr_algo; - int rc; - *out = NULL; + *r_result = NULL; - nbits = pubkey_nbits( PUBKEY_ALGO_ECDH, pkey ); + nbits = pubkey_nbits (PUBKEY_ALGO_ECDH, pkey); + if (!nbits) + return gpg_error (GPG_ERR_TOO_SHORT); { size_t nbytes; + /* Extract x component of the shared point: this is the actual - shared secret */ + shared secret. */ nbytes = (mpi_get_nbits (pkey[1] /* public point */)+7)/8; - secret_x = xmalloc_secure( nbytes ); - rc = gcry_mpi_print (GCRYMPI_FMT_USG, secret_x, nbytes, - &nbytes, shared_mpi); - if (rc) + secret_x = xtrymalloc_secure (nbytes); + if (!secret_x) + return gpg_error_from_syserror (); + + err = gcry_mpi_print (GCRYMPI_FMT_USG, secret_x, nbytes, + &nbytes, shared_mpi); + if (err) { xfree (secret_x); - log_error ("ec ephemeral export of shared point failed: %s\n", - gpg_strerror (rc)); - return rc; + log_error ("ECDH ephemeral export of shared point failed: %s\n", + gpg_strerror (err)); + return err; } + + /* fixme: explain what we are doing. */ 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 ); + log_printhex ("ECDH shared secret X is:", secret_x, secret_x_size ); } /*** We have now the shared secret bytes in secret_x. ***/ /* At this point we are done with PK encryption and the rest of the * function uses symmetric key encryption techniques to protect the - * input 'data'. The following two sections will simply replace + * input DATA. The following two sections will simply replace * current secret_x with a value derived from it. This will become * a KEK. */ { IOBUF obuf = iobuf_temp(); - rc = iobuf_write_size_body_mpi ( obuf, pkey[2] ); /* KEK params */ + err = iobuf_write_size_body_mpi ( obuf, pkey[2] ); /* KEK params */ kdf_params_size = iobuf_temp_to_buffer (obuf, kdf_params, sizeof(kdf_params)); @@ -185,11 +198,11 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, obuf = iobuf_temp(); /* variable-length field 1, curve name OID */ - rc = iobuf_write_size_body_mpi ( obuf, pkey[0] ); + err = iobuf_write_size_body_mpi ( obuf, pkey[0] ); /* fixed-length field 2 */ iobuf_put (obuf, PUBKEY_ALGO_ECDH); /* variable-length field 3, KDF params */ - rc = (rc ? rc : iobuf_write_size_body_mpi ( obuf, pkey[2] )); + err = (err ? err : iobuf_write_size_body_mpi ( obuf, pkey[2] )); /* fixed-length field 4 */ iobuf_write (obuf, "Anonymous Sender ", 20); /* fixed-length field 5, recipient fp */ @@ -198,8 +211,8 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, kdf_params_size = iobuf_temp_to_buffer (obuf, kdf_params, sizeof(kdf_params)); iobuf_close (obuf); - if (rc) - return rc; + if (err) + return err; if(DBG_CIPHER) log_printhex ("ecdh KDF message params are:", @@ -211,10 +224,10 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, gcry_md_hd_t h; int old_size; - rc = gcry_md_open (&h, kdf_hash_algo, 0); - if(rc) + err = gcry_md_open (&h, kdf_hash_algo, 0); + if(err) log_bug ("gcry_md_open failed for algo %d: %s", - kdf_hash_algo, gpg_strerror (gcry_error(rc))); + kdf_hash_algo, gpg_strerror (gcry_error(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 */ @@ -248,22 +261,22 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, gcry_mpi_t result; - rc = gcry_cipher_open (&hd, kdf_encr_algo, GCRY_CIPHER_MODE_AESWRAP, 0); - if (rc) + err = gcry_cipher_open (&hd, kdf_encr_algo, GCRY_CIPHER_MODE_AESWRAP, 0); + if (err) { log_error ("ecdh failed to initialize AESWRAP: %s\n", - gpg_strerror (rc)); - return rc; + gpg_strerror (err)); + return err; } - rc = gcry_cipher_setkey (hd, secret_x, secret_x_size); + err = gcry_cipher_setkey (hd, secret_x, secret_x_size); xfree( secret_x ); - if (rc) + if (err) { gcry_cipher_close (hd); log_error ("ecdh failed in gcry_cipher_setkey: %s\n", - gpg_strerror (rc)); - return rc; + gpg_strerror (err)); + return err; } data_buf_size = (gcry_mpi_get_nbits(data)+7)/8; @@ -282,52 +295,52 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, /* Write data MPI into the end of data_buf. data_buf is size aeswrap data. */ - rc = gcry_mpi_print (GCRYMPI_FMT_USG, in, + err = gcry_mpi_print (GCRYMPI_FMT_USG, in, data_buf_size, &nbytes, data/*in*/); - if (rc) + if (err) { - log_error ("ecdh failed to export DEK: %s\n", gpg_strerror (rc)); + log_error ("ecdh failed to export DEK: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); xfree (data_buf); - return rc; + return err; } if (DBG_CIPHER) log_printhex ("ecdh encrypting :", in, data_buf_size ); - rc = gcry_cipher_encrypt (hd, data_buf+1, data_buf_size+8, + err = gcry_cipher_encrypt (hd, data_buf+1, data_buf_size+8, in, data_buf_size); memset (in, 0, data_buf_size); gcry_cipher_close (hd); - if (rc) + if (err) { log_error ("ecdh failed in gcry_cipher_encrypt: %s\n", - gpg_strerror (rc)); + gpg_strerror (err)); xfree (data_buf); - return rc; + return err; } data_buf[0] = data_buf_size+8; if (DBG_CIPHER) log_printhex ("ecdh encrypted to:", data_buf+1, data_buf[0] ); - rc = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, + err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, data_buf, 1+data_buf[0], NULL); /* (byte)size + aeswrap of DEK */ xfree( data_buf ); - if (rc) + if (err) { - log_error ("ecdh failed to create an MPI: %s\n", gpg_strerror (rc)); - return rc; + log_error ("ecdh failed to create an MPI: %s\n", gpg_strerror (err)); + return err; } - *out = result; + *r_result = result; } else { byte *in; - rc = gcry_mpi_print (GCRYMPI_FMT_USG, data_buf, data_buf_size, + err = gcry_mpi_print (GCRYMPI_FMT_USG, data_buf, data_buf_size, &nbytes, data/*in*/); if (nbytes != data_buf_size || data_buf[0] != data_buf_size-1) { @@ -341,15 +354,15 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, if (DBG_CIPHER) log_printhex ("ecdh decrypting :", data_buf+1, data_buf_size); - rc = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1, + err = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1, data_buf_size); gcry_cipher_close (hd); - if (rc) + if (err) { log_error ("ecdh failed in gcry_cipher_decrypt: %s\n", - gpg_strerror (rc)); + gpg_strerror (err)); xfree (data_buf); - return rc; + return err; } data_buf_size -= 8; @@ -365,20 +378,20 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, /* return GPG_ERR_BAD_KEY; */ /* } */ - rc = gcry_mpi_scan ( &result, GCRYMPI_FMT_USG, in, data_buf_size, NULL); + err = gcry_mpi_scan ( &result, GCRYMPI_FMT_USG, in, data_buf_size, NULL); xfree (data_buf); - if (rc) + if (err) { log_error ("ecdh failed to create a plain text MPI: %s\n", - gpg_strerror (rc)); - return rc; + gpg_strerror (err)); + return err; } - *out = result; + *r_result = result; } } - return rc; + return err; } @@ -405,76 +418,31 @@ gen_k (unsigned nbits) return k; } -/* Perform ECDH encryption, which involves ECDH key generation. */ -int -pk_ecdh_encrypt (gcry_mpi_t *resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], - gcry_mpi_t data, gcry_mpi_t * pkey) -{ - gcry_sexp_t s_ciph, s_data, s_pkey; - int nbits; - int rc; +/* Generate an ephemeral key for the public ECDH key in PKEY. On + success the generated key is stored at R_K; on failure NULL is + stored at R_K and an error code returned. */ +gpg_error_t +pk_ecdh_generate_ephemeral_key (gcry_mpi_t *pkey, gcry_mpi_t *r_k) +{ + unsigned int nbits; gcry_mpi_t k; - nbits = pubkey_nbits (PUBKEY_ALGO_ECDH, pkey); - - /*** Generate an ephemeral key, actually, a scalar. ***/ + *r_k = NULL; + nbits = pubkey_nbits (PUBKEY_ALGO_ECDH, pkey); + if (!nbits) + return gpg_error (GPG_ERR_TOO_SHORT); k = gen_k (nbits); - if( k == NULL ) + if (!k) BUG (); - /*** Done with ephemeral key generation. - * Now use ephemeral secret to get the shared secret. ***/ - - rc = gcry_sexp_build (&s_pkey, NULL, - "(public-key(ecdh(c%m)(q%m)(p%m)))", - pkey[0], pkey[1], pkey[2]); - if (rc) - BUG (); - - /* Put the data into a simple list. */ - /* Ephemeral scalar goes as data. */ - if (gcry_sexp_build (&s_data, NULL, "%m", k)) - BUG (); - - /* Pass it to libgcrypt. */ - rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey); - gcry_sexp_release (s_data); - gcry_sexp_release (s_pkey); - if (rc) - return rc; - - /* Finally, perform encryption. */ - - { - /* ... and get the shared point/ */ - gcry_mpi_t shared; - - shared = mpi_from_sexp (s_ciph, "a"); - gcry_sexp_release (s_ciph); - /* Ephemeral public key. */ - resarr[0] = mpi_from_sexp (s_ciph, "b"); - - if (DBG_CIPHER) - { - unsigned char *buffer; - - if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, resarr[0])) - BUG (); - log_debug("ephemeral key MPI: %s\n", buffer); - gcry_free( buffer ); - } - - rc = pk_ecdh_encrypt_with_shared_point (1 /*=encrypton*/, shared, - pk_fp, data, pkey, resarr+1); - mpi_release (shared); - } - - return rc; + *r_k = k; + return 0; } + /* Perform ECDH decryption. */ int pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN], diff --git a/g10/misc.c b/g10/misc.c index bdd797c..fd00ec6 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -1423,7 +1423,7 @@ pubkey_nbits( int algo, gcry_mpi_t *key ) int rc, nbits; gcry_sexp_t sexp; -#warning Why this assert +#warning FIXME: We are mixing OpenPGP And CGrypt Ids assert( algo != GCRY_PK_ECDSA && algo != GCRY_PK_ECDH ); if( algo == GCRY_PK_DSA ) { diff --git a/g10/pkglue.c b/g10/pkglue.c index f5c8597..3aba4e4 100644 --- a/g10/pkglue.c +++ b/g10/pkglue.c @@ -28,6 +28,7 @@ #include "util.h" #include "pkglue.h" #include "main.h" +#include "options.h" /* FIXME: Better chnage the fucntion name because mpi_ is used by gcrypt macros. */ @@ -156,26 +157,39 @@ pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, rc = gcry_sexp_build (&s_pkey, NULL, "(public-key(elg(p%m)(g%m)(y%m)))", pkey[0], pkey[1], pkey[2]); + /* Put DATA into a simplified S-expression. */ + if (rc || gcry_sexp_build (&s_data, NULL, "%m", data)) + BUG (); + } else if (algo == GCRY_PK_RSA || algo == GCRY_PK_RSA_E) { rc = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%m)(e%m)))", pkey[0], pkey[1]); + /* Put DATA into a simplified S-expression. */ + if (rc || gcry_sexp_build (&s_data, NULL, "%m", data)) + BUG (); } else if (algo == PUBKEY_ALGO_ECDH) { - return pk_ecdh_encrypt (resarr, pk_fp, data, pkey); + gcry_mpi_t k; + + rc = pk_ecdh_generate_ephemeral_key (pkey, &k); + if (rc) + return rc; + + /* Now use the ephemeral secret to compute the shared point. */ + rc = gcry_sexp_build (&s_pkey, NULL, + "(public-key(ecdh(c%m)(q%m)(p%m)))", + pkey[0], pkey[1], pkey[2]); + /* Put K into a simplified S-expression. */ + if (rc || gcry_sexp_build (&s_data, NULL, "%m", k)) + BUG (); } else - return GPG_ERR_PUBKEY_ALGO; - - if (rc) - BUG (); + return gpg_error (GPG_ERR_PUBKEY_ALGO); - /* Put the data into a simple list. */ - if (gcry_sexp_build (&s_data, NULL, "%m", data)) - BUG (); /* Pass it to libgcrypt. */ rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey); @@ -184,12 +198,42 @@ pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, if (rc) ; - else - { /* Add better error handling or make gnupg use S-Exp directly. */ + else if (algo == PUBKEY_ALGO_ECDH) + { + gcry_mpi_t shared, public, result; + + /* Get the shared point and the ephemeral public key. */ + shared = mpi_from_sexp (s_ciph, "a"); + public = mpi_from_sexp (s_ciph, "b"); + gcry_sexp_release (s_ciph); + s_ciph = NULL; + if (DBG_CIPHER) + { + log_debug ("ECDH ephemeral key:"); + gcry_mpi_dump (public); + log_printf ("\n"); + } + + result = NULL; + rc = pk_ecdh_encrypt_with_shared_point (1 /*=encrypton*/, shared, + pk_fp, data, pkey, &result); + gcry_mpi_release (shared); + if (!rc) + { + resarr[0] = public; + resarr[1] = result; + } + else + { + gcry_mpi_release (public); + gcry_mpi_release (result); + } + } + else /* Elgamal or RSA case. */ + { /* Fixme: Add better error handling or make gnupg use + S-expressions directly. */ resarr[0] = mpi_from_sexp (s_ciph, "a"); - if (algo != GCRY_PK_RSA - && algo != GCRY_PK_RSA_E - && algo != PUBKEY_ALGO_ECDH) + if (algo != GCRY_PK_RSA && algo != GCRY_PK_RSA_E) resarr[1] = mpi_from_sexp (s_ciph, "b"); } diff --git a/g10/pkglue.h b/g10/pkglue.h index b1cfbe5..98d8c14 100644 --- a/g10/pkglue.h +++ b/g10/pkglue.h @@ -33,6 +33,13 @@ int pk_check_secret_key (int algo, gcry_mpi_t *skey); /*-- ecdh.c --*/ byte *pk_ecdh_default_params (unsigned int qbits, size_t *sizeout); +gpg_error_t pk_ecdh_generate_ephemeral_key (gcry_mpi_t *pkey, gcry_mpi_t *r_k); +gpg_error_t 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 *out); + int pk_ecdh_encrypt (gcry_mpi_t *resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t * pkey); int pk_ecdh_decrypt (gcry_mpi_t *result, const byte sk_fp[MAX_FINGERPRINT_LEN], commit 302c5a826c0fd0b2aab85ad3c287b65429db2066 Author: Werner Koch Date: Tue Jan 25 17:48:51 2011 +0100 More ECDH code cleanups diff --git a/g10/ChangeLog b/g10/ChangeLog index 8011464..3ce4d1f 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,5 +1,9 @@ 2011-01-25 Werner Koch + * ecdh.c (pk_ecdh_default_params_to_mpi): Remove. + (pk_ecdh_default_params): Rewrite. Factor KEK table out to .. + (kek_params_table): .. here. + * pubkey-enc.c (get_it): Fix assertion. Use GPG_ERR_WRONG_SECKEY instead of log_fatal. Add safety checks for NFRAME. @@ -14,6 +18,8 @@ (pk_ecc_keypair_gen): Fold it into .. (gen_ecc): .. this. (ask_keysize): Use proper rounding for ECC. + (pk_ecc_build_key_params): Remove NBITSSTR. + * verify-stubs.c: Remove. 2011-01-20 Werner Koch diff --git a/g10/ecdh.c b/g10/ecdh.c index cb251fe..1fa36aa 100644 --- a/g10/ecdh.c +++ b/g10/ecdh.c @@ -30,26 +30,15 @@ #include "main.h" #include "options.h" -gcry_mpi_t -pk_ecdh_default_params_to_mpi (int qbits) +/* A table with the default KEK parameters used by GnuPG. */ +static const struct { - gpg_error_t err; - gcry_mpi_t result; - /* Defaults are the strongest possible choices. Performance is not - an issue here, only interoperability. */ - byte kek_params[4] = { - 3 /*size of following field*/, - 1 /*fixed version for KDF+AESWRAP*/, - DIGEST_ALGO_SHA512 /* KEK MD */, - CIPHER_ALGO_AES256 /*KEK AESWRAP alg*/ - }; - int i; - - static const struct { - int qbits; - int openpgp_hash_id; - int openpgp_cipher_id; - } kek_params_table[] = { + unsigned int qbits; + int openpgp_hash_id; /* KEK digest algorithm. */ + int openpgp_cipher_id; /* KEK cipher algorithm. */ +} kek_params_table[] = + /* Note: Must be sorted by ascending values for QBITS. */ + { { 256, DIGEST_ALGO_SHA256, CIPHER_ALGO_AES }, { 384, DIGEST_ALGO_SHA384, CIPHER_ALGO_AES256 }, @@ -57,77 +46,44 @@ pk_ecdh_default_params_to_mpi (int qbits) { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 } }; - for (i=0; i= qbits) - { - kek_params[2] = kek_params_table[i].openpgp_hash_id; - kek_params[3] = kek_params_table[i].openpgp_cipher_id; - break; - } - } - if (DBG_CIPHER) - log_printhex ("ecdh kek params are", kek_params, sizeof(kek_params) ); - - err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, - kek_params, sizeof(kek_params), NULL); - if (err) - log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); - - return result; -} /* Returns allocated (binary) KEK parameters; the size is returned in - * sizeout. The caller must free the returned value with xfree. - * Returns NULL on error. - */ + sizeout. The caller must free the returned value. Returns NULL + and sets ERRNO on error. */ byte * -pk_ecdh_default_params (int qbits, size_t *sizeout) +pk_ecdh_default_params (unsigned int qbits, size_t *sizeout) { - /* Defaults are the strongest possible choices. Performance is not - an issue here, only interoperability. */ - byte kek_params[4] = { - 3 /*size of following field*/, - 1 /*fixed version for KDF+AESWRAP*/, - DIGEST_ALGO_SHA512 /* KEK MD */, - CIPHER_ALGO_AES256 /* KEK AESWRAP alg */ - }; + byte kek_params[4]; int i; - - static const struct { - int qbits; - int openpgp_hash_id; - int openpgp_cipher_id; - } kek_params_table[] = { - { 256, DIGEST_ALGO_SHA256, CIPHER_ALGO_AES }, - { 384, DIGEST_ALGO_SHA384, CIPHER_ALGO_AES256 }, - /* Note: 528 is 521 rounded to the 8 bit boundary */ - { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 } - }; - - byte *p; + byte *buffer; - *sizeout = 0; + kek_params[0] = 3; /* Number of bytes to follow. */ + kek_params[1] = 1; /* Version for KDF+AESWRAP. */ - for (i=0; i= qbits) + if (kek_params_table[i].qbits >= qbits + || i+1 == DIM (kek_params_table)) { kek_params[2] = kek_params_table[i].openpgp_hash_id; kek_params[3] = kek_params_table[i].openpgp_cipher_id; break; } } - if (DBG_CIPHER ) - log_printhex ("ecdh kek params are", kek_params, sizeof(kek_params)); - - p = xtrymalloc (sizeof(kek_params)); - if (!p) + assert (i < DIM (kek_params_table)); + if (DBG_CIPHER) + log_printhex ("ECDH KEK params are", kek_params, sizeof(kek_params) ); + + buffer = xtrymalloc (sizeof(kek_params)); + if (!buffer) return NULL; - memcpy (p, kek_params, sizeof(kek_params)); - *sizeout = sizeof(kek_params); - return p; + memcpy (buffer, kek_params, sizeof (kek_params)); + *sizeout = sizeof (kek_params); + return buffer; } diff --git a/g10/keygen.c b/g10/keygen.c index 366bedf..b42121b 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -1329,7 +1329,7 @@ gen_dsa (unsigned int nbits, KBNODE pub_root, -/* Create an S-expression string out QBITS, ALGO and the TRANSIENT +/* Create an S-expression string out of QBITS, ALGO and the TRANSIENT flag. On success a malloced string is returned, on failure NULL and ERRNO is set. */ static char * @@ -1337,56 +1337,63 @@ pk_ecc_build_key_params (int qbits, int algo, int transient) { byte *kek_params = NULL; size_t kek_params_size; - char nbitsstr[35]; char qbitsstr[35]; - char *keyparms; - int n; + char *result; + size_t n; /* KEK parameters are only needed for long term key generation. */ if (!transient && algo == PUBKEY_ALGO_ECDH) - kek_params = pk_ecdh_default_params (qbits, &kek_params_size); + { + kek_params = pk_ecdh_default_params (qbits, &kek_params_size); + if (!kek_params) + return NULL; + } else kek_params = NULL; - snprintf (nbitsstr, sizeof nbitsstr, "%u", qbits); snprintf (qbitsstr, sizeof qbitsstr, "%u", qbits); if (algo == PUBKEY_ALGO_ECDSA || !kek_params) { - keyparms = xtryasprintf ("(genkey(%s(nbits %zu:%s)" + result = xtryasprintf ("(genkey(%s(nbits %zu:%s)" /**/ "(qbits %zu:%s)" /**/ "(transient-key 1:%d)))", algo == PUBKEY_ALGO_ECDSA ? "ecdsa" : "ecdh", - strlen (nbitsstr), nbitsstr, + strlen (qbitsstr), qbitsstr, strlen (qbitsstr), qbitsstr, transient); } else { - assert (kek_params); + char *tmpstr; - keyparms = xtryasprintf ("(genkey(ecdh(nbits %zu:%s)" - /**/ "(qbits %zu:%s)" - /**/ "(transient-key 1:%d)" - /**/ "(kek-params %zu:", - strlen (nbitsstr), nbitsstr, - strlen (qbitsstr), qbitsstr, - transient, - kek_params_size); - if (keyparms) + assert (kek_params); + tmpstr = xtryasprintf ("(genkey(ecdh(nbits %zu:%s)" + /**/ "(qbits %zu:%s)" + /**/ "(transient-key 1:%d)" + /**/ "(kek-params %zu:", + strlen (qbitsstr), qbitsstr, + strlen (qbitsstr), qbitsstr, + transient, + kek_params_size); + if (!tmpstr) { - n = strlen (keyparms); - keyparms = xtryrealloc (keyparms, n + kek_params_size + 4); + xfree (kek_params); + return NULL; } - if (!keyparms) + /* Append the binary KEK parmas. */ + n = strlen (tmpstr); + result = xtryrealloc (tmpstr, n + kek_params_size + 4); + if (!result) { + xfree (tmpstr); xfree (kek_params); return NULL; } - memcpy (keyparms+n, kek_params, kek_params_size); - xfree (kek_params); - memcpy (keyparms+n+kek_params_size, ")))", 4); + memcpy (result + n, kek_params, kek_params_size); + strcpy (result + n + kek_params_size, ")))"); } - return keyparms; + xfree (kek_params); + return result; } diff --git a/g10/pkglue.h b/g10/pkglue.h index 0ceb43f..b1cfbe5 100644 --- a/g10/pkglue.h +++ b/g10/pkglue.h @@ -20,6 +20,7 @@ #ifndef GNUPG_G10_PKGLUE_H #define GNUPG_G10_PKGLUE_H +/*-- pkglue.c --*/ gcry_mpi_t mpi_from_sexp (gcry_sexp_t sexp, const char * item); int pk_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, @@ -29,12 +30,13 @@ int pk_encrypt (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *pkey); int pk_check_secret_key (int algo, gcry_mpi_t *skey); + +/*-- ecdh.c --*/ +byte *pk_ecdh_default_params (unsigned int qbits, size_t *sizeout); int pk_ecdh_encrypt (gcry_mpi_t *resarr, const byte pk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t * pkey); int pk_ecdh_decrypt (gcry_mpi_t *result, const byte sk_fp[MAX_FINGERPRINT_LEN], gcry_mpi_t data, gcry_mpi_t shared, gcry_mpi_t * skey); -gcry_mpi_t pk_ecdh_default_params_to_mpi (int qbits); -byte *pk_ecdh_default_params (int qbits, size_t *sizeout); #endif /*GNUPG_G10_PKGLUE_H*/ commit 638dca5dbc7e119ff5a05dbdb109fbc171624605 Author: Werner Koch Date: Tue Jan 25 16:54:18 2011 +0100 Editorial cleanups of keygen.c Also fixed a regression introduced by me in pubkey_enc.c. Added extra checks. Removed unused code. diff --git a/g10/ChangeLog b/g10/ChangeLog index 4c28363..8011464 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,21 @@ +2011-01-25 Werner Koch + + * pubkey-enc.c (get_it): Fix assertion. + Use GPG_ERR_WRONG_SECKEY instead of log_fatal. Add safety checks + for NFRAME. + + * main.h (KEYGEN_FLAG_NO_PROTECTION, KEYGEN_FLAG_TRANSIENT_KEY): + Move back to .. + * keygen.c: .. here. + (pk_ecc_keypair_gen): Make static. + (common_key_gen): Fold back into .. + (common_gen): .. this. + (delme__pk_ecc_build_sexp): Remove unused function. + (pk_ecc_keypair_gen): Fold it into .. + (gen_ecc): .. this. + (ask_keysize): Use proper rounding for ECC. + * verify-stubs.c: Remove. + 2011-01-20 Werner Koch * keyserver.c: Rewrite most stuff for use with dirmngr. Get rid diff --git a/g10/Makefile.am b/g10/Makefile.am index 5d24702..a28b2ab 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -111,8 +111,7 @@ gpg2_SOURCES = gpg.c \ gpgv2_SOURCES = gpgv.c \ $(common_source) \ - verify.c \ - verify-stubs.c + verify.c #gpgd_SOURCES = gpgd.c \ # ks-proto.h \ diff --git a/g10/keygen.c b/g10/keygen.c index e75da79..366bedf 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -1,6 +1,6 @@ /* keygen.c - generate a key pair - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - * 2006, 2007, 2009, 2010 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + * 2007, 2009, 2010, 2011 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -18,7 +18,6 @@ * along with this program; if not, see . */ -#warning wk: check these changes. #include #include #include @@ -51,6 +50,11 @@ #define DEFAULT_STD_ALGO GCRY_PK_RSA #define DEFAULT_STD_KEYSIZE 2048 +/* Flag bits used during key generation. */ +#define KEYGEN_FLAG_NO_PROTECTION 1 +#define KEYGEN_FLAG_TRANSIENT_KEY 2 + +/* Maximum number of supported algorithm preferences. */ #define MAX_PREFS 30 enum para_name { @@ -1128,16 +1132,17 @@ key_from_sexp (gcry_mpi_t *array, gcry_sexp_t sexp, } +/* Common code for the key generation fucntion gen_xxx. */ static int -common_key_gen (const char *keyparms, int algo, const char *algoelem, - int keygen_flags, char **cache_nonce_addr, PKT_public_key **pk_out) +common_gen (const char *keyparms, int algo, const char *algoelem, + kbnode_t pub_root, u32 timestamp, u32 expireval, int is_subkey, + int keygen_flags, char **cache_nonce_addr) { int err; + PACKET *pkt; PKT_public_key *pk; gcry_sexp_t s_key; - *pk_out = NULL; - err = agent_genkey (NULL, cache_nonce_addr, keyparms, !!(keygen_flags & KEYGEN_FLAG_NO_PROTECTION), &s_key); if (err) @@ -1154,7 +1159,10 @@ common_key_gen (const char *keyparms, int algo, const char *algoelem, return err; } + pk->timestamp = timestamp; pk->version = 4; + if (expireval) + pk->expiredate = pk->timestamp + expireval; pk->pubkey_algo = algo; err = key_from_sexp (pk->pkey, s_key, "public-key", algoelem); @@ -1167,45 +1175,21 @@ common_key_gen (const char *keyparms, int algo, const char *algoelem, } gcry_sexp_release (s_key); - *pk_out = pk; + pkt = xtrycalloc (1, sizeof *pkt); + if (!pkt) + { + err = gpg_error_from_syserror (); + free_public_key (pk); + return err; + } + + pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY; + pkt->pkt.public_key = pk; + add_kbnode (pub_root, new_kbnode (pkt)); return 0; } -/* Common code for the key generation fucntion gen_xxx. */ -static int -common_gen (const char *keyparms, int algo, const char *algoelem, - kbnode_t pub_root, u32 timestamp, u32 expireval, int is_subkey, - int keygen_flags, char **cache_nonce_addr) -{ - PKT_public_key *pk; - int err; - - err = common_key_gen( keyparms, algo, algoelem, keygen_flags, cache_nonce_addr, &pk ); - - if( !err ) { - PACKET *pkt; - - pk->timestamp = timestamp; - if (expireval) - pk->expiredate = pk->timestamp + expireval; - - pkt = xtrycalloc (1, sizeof *pkt); - if (!pkt) - { - err = gpg_error_from_syserror (); - free_public_key (pk); - return err; - } - - pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY; - pkt->pkt.public_key = pk; - - add_kbnode (pub_root, new_kbnode (pkt)); - } - - return err; -} /* * Generate an Elgamal key. @@ -1343,40 +1327,14 @@ gen_dsa (unsigned int nbits, KBNODE pub_root, return err; } -/* Returns allocated ECC key generation S-explression - call gcry_sexp_release ( out ) to free it. - */ -static int -delme__pk_ecc_build_sexp( int qbits, int algo, int is_long_term, gcry_sexp_t *out ) { - gcry_mpi_t kek_params; - char *kek_params_s; - int rc; - if( is_long_term && algo == PUBKEY_ALGO_ECDH ) - kek_params = pk_ecdh_default_params_to_mpi( qbits ); - else - kek_params = NULL; - - if( kek_params ) { - kek_params_s = mpi2hex( kek_params ); - mpi_release( kek_params ); - } - - rc = gcry_sexp_build (out, NULL, - algo == PUBKEY_ALGO_ECDSA ? - "(genkey(ecdsa(nbits %d)(qbits %d)))" : - "(genkey(ecdh(nbits %d)(qbits %d)(transient-key %d)(kek-params %s)))", - (int)qbits, (int)qbits, (int)(is_long_term==0), kek_params_s); - xfree( kek_params_s ); - if (rc) { - log_debug("ec gen gcry_sexp_build failed: %s\n", gpg_strerror (rc)); - return rc; - } - return 0; -} -static char * -pk_ecc_build_key_params( int qbits, int algo, int transient ) { +/* Create an S-expression string out QBITS, ALGO and the TRANSIENT + flag. On success a malloced string is returned, on failure NULL + and ERRNO is set. */ +static char * +pk_ecc_build_key_params (int qbits, int algo, int transient) +{ byte *kek_params = NULL; size_t kek_params_size; char nbitsstr[35]; @@ -1384,142 +1342,105 @@ pk_ecc_build_key_params( int qbits, int algo, int transient ) { char *keyparms; int n; - /* KEK parameters are only needed for long term key generation */ - if( !transient && algo == PUBKEY_ALGO_ECDH ) - kek_params = pk_ecdh_default_params( qbits, &kek_params_size ); + /* KEK parameters are only needed for long term key generation. */ + if (!transient && algo == PUBKEY_ALGO_ECDH) + kek_params = pk_ecdh_default_params (qbits, &kek_params_size); else kek_params = NULL; snprintf (nbitsstr, sizeof nbitsstr, "%u", qbits); snprintf (qbitsstr, sizeof qbitsstr, "%u", qbits); - if( algo == PUBKEY_ALGO_ECDSA || kek_params == NULL ) - keyparms = xtryasprintf ( - "(genkey(%s(nbits %zu:%s)(qbits %zu:%s)(transient-key 1:%d)))", - algo == PUBKEY_ALGO_ECDSA ? "ecdsa" : "ecdh", - strlen (nbitsstr), nbitsstr, - strlen (qbitsstr), qbitsstr, - transient ); - else { - assert( kek_params != NULL ); - keyparms = xtryasprintf ( - "(genkey(ecdh(nbits %zu:%s)(qbits %zu:%s)(transient-key 1:%d)(kek-params %u:", - strlen (nbitsstr), nbitsstr, - strlen (qbitsstr), qbitsstr, - transient, - (unsigned)kek_params_size ); - if( keyparms != NULL ) { - n = strlen(keyparms); - keyparms = xtryrealloc( keyparms, n + kek_params_size + 4 ); + if (algo == PUBKEY_ALGO_ECDSA || !kek_params) + { + keyparms = xtryasprintf ("(genkey(%s(nbits %zu:%s)" + /**/ "(qbits %zu:%s)" + /**/ "(transient-key 1:%d)))", + algo == PUBKEY_ALGO_ECDSA ? "ecdsa" : "ecdh", + strlen (nbitsstr), nbitsstr, + strlen (qbitsstr), qbitsstr, + transient); } - if( keyparms == NULL ) { - xfree( kek_params ); - return NULL; + else + { + assert (kek_params); + + keyparms = xtryasprintf ("(genkey(ecdh(nbits %zu:%s)" + /**/ "(qbits %zu:%s)" + /**/ "(transient-key 1:%d)" + /**/ "(kek-params %zu:", + strlen (nbitsstr), nbitsstr, + strlen (qbitsstr), qbitsstr, + transient, + kek_params_size); + if (keyparms) + { + n = strlen (keyparms); + keyparms = xtryrealloc (keyparms, n + kek_params_size + 4); + } + if (!keyparms) + { + xfree (kek_params); + return NULL; + } + memcpy (keyparms+n, kek_params, kek_params_size); + xfree (kek_params); + memcpy (keyparms+n+kek_params_size, ")))", 4); } - memcpy( keyparms+n, kek_params, kek_params_size ); - xfree( kek_params ); - memcpy( keyparms+n+kek_params_size, ")))", 4 ); - } return keyparms; } -/* This common function is used in this file and also to generate ephemeral keys for ECDH. - * Caller must call free_public_key and free_secret_key */ -int -pk_ecc_keypair_gen( PKT_public_key **pk_out, int algo, int keygen_flags, char **cache_nonce_addr, unsigned nbits) { + +/* + * Generate an ECC key + */ +static gpg_error_t +gen_ecc (int algo, unsigned int nbits, KBNODE pub_root, + u32 timestamp, u32 expireval, int is_subkey, + int keygen_flags, char **cache_nonce_addr) +{ int err; unsigned int qbits; char *keyparms; - // PUBKEY_ALGO_ECDH, PUBKEY_ALGO_ECDSA - static const char * const ec_pub_params[2] = { "cqp", "cq" }; - //static const char * const ec_priv_params[2] = { "cqpd", "cqd" }; - assert( algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH ); - assert( PUBKEY_ALGO_ECDSA == PUBKEY_ALGO_ECDH + 1 ); + assert (algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH); - *pk_out = NULL; - - if( pubkey_get_npkey (PUBKEY_ALGO_ECDSA) != 2 || pubkey_get_nskey (PUBKEY_ALGO_ECDSA) != 3 || - pubkey_get_npkey (PUBKEY_ALGO_ECDH) != 3 || pubkey_get_nskey (PUBKEY_ALGO_ECDH) != 4 ) - { - log_info(_("incompatible version of gcrypt library (expect named curve logic for ECC)\n") ); - return GPG_ERR_EPROGMISMATCH; - } + if (pubkey_get_npkey (PUBKEY_ALGO_ECDSA) != 2 + || pubkey_get_nskey (PUBKEY_ALGO_ECDSA) != 3 + || pubkey_get_npkey (PUBKEY_ALGO_ECDH) != 3 + || pubkey_get_nskey (PUBKEY_ALGO_ECDH) != 4) + { + log_error ("broken version of Libgcrypt\n"); + return gpg_error (GPG_ERR_INTERNAL); /* ABI silently changed. */ + } - if ( nbits != 256 && nbits != 384 && nbits != 521 ) + if (nbits != 256 && nbits != 384 && nbits != 521) { - log_info(_("keysize invalid; using 256 bits instead of passed in %d\n"), nbits ); + log_info (_("keysize invalid; using %u bits\n"), 256); + /* FIXME: Where do we set it to 256? */ } - /* - Figure out a q size based on the key size. See gen_dsa for more details. - Due to 8-bit rounding we may get 528 here instead of 521 - */ + /* Figure out a Q size based on the key size. See gen_dsa for more + details. Due to 8-bit rounding we may get 528 here instead of 521. */ nbits = qbits = (nbits < 521 ? nbits : 521 ); - keyparms = pk_ecc_build_key_params(qbits, algo, !!((keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY) && (keygen_flags & KEYGEN_FLAG_NO_PROTECTION)) ); - if (!keyparms) { - err = gpg_error_from_syserror (); - log_error ("ec pk_ecc_build_key_params failed: %s\n", gpg_strerror (err) ); - } + keyparms = pk_ecc_build_key_params + (qbits, algo, !!( (keygen_flags & KEYGEN_FLAG_TRANSIENT_KEY) + && (keygen_flags & KEYGEN_FLAG_NO_PROTECTION)) ); + if (!keyparms) + { + err = gpg_error_from_syserror (); + log_error ("ecc pk_ecc_build_key_params failed: %s\n", + gpg_strerror (err)); + } else { - err = common_key_gen (keyparms, algo, ec_pub_params[algo-PUBKEY_ALGO_ECDH], - keygen_flags, cache_nonce_addr, pk_out); + err = common_gen (keyparms, algo, + algo == PUBKEY_ALGO_ECDSA? "cq" : "cqp", + pub_root, timestamp, expireval, is_subkey, + keygen_flags, cache_nonce_addr); xfree (keyparms); } -#if 0 - /* always allocase seckey_info for EC keys. TODO: is this needed? */ - if( *pk_out ) { - struct seckey_info *ski; - - (*pk_out)->seckey_info = ski = xtrycalloc (1, sizeof *ski); - if (!(*pk_out)->seckey_info) { - free_public_key(*pk_out); - *pk_out = NULL; - return gpg_error_from_syserror (); - } - - ski->is_protected = 0; - ski->algo = 0; - } -#endif - - return err; -} - - -/**************** - * Generate an ECC OpenPGP key - */ -static gpg_error_t -gen_ecc (int algo, unsigned int nbits, KBNODE pub_root, - u32 timestamp, u32 expireval, int is_subkey, - int keygen_flags, char **cache_nonce_addr) -{ - int rc; - PACKET *pkt; - PKT_public_key *pk; - - rc = pk_ecc_keypair_gen( &pk, algo, keygen_flags, cache_nonce_addr, nbits ); - if( rc ) - return rc; - - /* the rest is very similar to common_gen */ - - pk->timestamp = timestamp; - if (expireval) - pk->expiredate = pk->timestamp + expireval; - - //assert( pk->seckey_info != NULL ); - /// TODO: the new agent-based model doesn't return private portion here (the pkey array is allocated, but private MPIs are NULL, so this will cause a crash... ) - ///pk->seckey_info->csum = checksum_mpi ( pk->pkey[algo==PUBKEY_ALGO_ECDSA ? 2 : 3] ); /* corresponds to 'd' in 'cqd' or 'cqpd' */ - - pkt = xmalloc_clear(sizeof *pkt); - pkt->pkttype = is_subkey ? PKT_PUBLIC_SUBKEY : PKT_PUBLIC_KEY; - pkt->pkt.public_key = pk; - add_kbnode(pub_root, new_kbnode( pkt )); - return 0; } @@ -1755,7 +1676,7 @@ ask_algo (int addmode, int *r_subkey_algo, unsigned int *r_usage) } tty_printf (_(" (%d) ECDSA and ECDH\n"), 9 ); - + for(;;) { *r_usage = 0; @@ -1877,7 +1798,7 @@ ask_keysize (int algo, unsigned int primary_keysize) tty_printf(_("%s keys may be between %u and %u bits long.\n"), openpgp_pk_algo_name (algo), min, max); - for(;;) + for (;;) { char *prompt, *answer; @@ -1899,28 +1820,34 @@ ask_keysize (int algo, unsigned int primary_keysize) break; } - tty_printf(_("Requested keysize is %u bits\n"), nbits ); + tty_printf (_("Requested keysize is %u bits\n"), nbits); leave: - if( algo == PUBKEY_ALGO_DSA && (nbits % 64) ) + if (algo == PUBKEY_ALGO_DSA && (nbits % 64)) { - if( !(algo == PUBKEY_ALGO_ECDSA && nbits==521) ) { - nbits = ((nbits + 63) / 64) * 64; - if (!autocomp) - tty_printf(_("rounded up to %u bits\n"), nbits ); - } + nbits = ((nbits + 63) / 64) * 64; + if (!autocomp) + tty_printf (_("rounded up to %u bits\n"), nbits); } - else if( algo == PUBKEY_ALGO_ECDH || algo == PUBKEY_ALGO_ECDSA ) { - if( nbits != 256 && nbits != 384 && nbits != 521 ) { - nbits = min; - tty_printf(_("unsupported ECDH value, corrected to the minimum %u bits\n"), nbits ); - } - } - else if( (nbits % 32) ) + else if (algo == PUBKEY_ALGO_ECDH || algo == PUBKEY_ALGO_ECDSA) + { + if (nbits != 256 && nbits != 384 && nbits != 521) + { + if (nbits < 256) + nbits = 256; + else if (nbits < 384) + nbits = 384; + else + nbits = 521; + if (!autocomp) + tty_printf (_("rounded to %u bits\n"), nbits); + } + } + else if ((nbits % 32)) { nbits = ((nbits + 31) / 32) * 32; if (!autocomp) - tty_printf(_("rounded up to %u bits\n"), nbits ); + tty_printf (_("rounded up to %u bits\n"), nbits ); } return nbits; @@ -2405,7 +2332,7 @@ do_create (int algo, unsigned int nbits, KBNODE pub_root, else if (algo == PUBKEY_ALGO_DSA) err = gen_dsa (nbits, pub_root, timestamp, expiredate, is_subkey, keygen_flags, cache_nonce_addr); - else if( algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH ) + else if (algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_ECDH) err = gen_ecc (algo, nbits, pub_root, timestamp, expiredate, is_subkey, keygen_flags, cache_nonce_addr); else if (algo == PUBKEY_ALGO_RSA) diff --git a/g10/main.h b/g10/main.h index 1b6f305..ea1ac2e 100644 --- a/g10/main.h +++ b/g10/main.h @@ -260,11 +260,6 @@ gpg_error_t generate_card_subkeypair (kbnode_t pub_keyblock, int save_unprotected_key_to_card (PKT_public_key *sk, int keyno); #endif -#define KEYGEN_FLAG_NO_PROTECTION 1 -#define KEYGEN_FLAG_TRANSIENT_KEY 2 -int pk_ecc_keypair_gen (PKT_public_key **pk_out, int algo, - int keygen_flags, char **cache_nonce_addr, - unsigned nbits); /*-- openfile.c --*/ int overwrite_filep( const char *fname ); diff --git a/g10/pubkey-enc.c b/g10/pubkey-enc.c index ddca41e..43f5419 100644 --- a/g10/pubkey-enc.c +++ b/g10/pubkey-enc.c @@ -145,18 +145,17 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) gcry_sexp_t s_data; char *desc; char *keygrip; - byte fp[MAX_FINGERPRINT_LEN]; + byte fp[MAX_FINGERPRINT_LEN]; size_t fpn; - const int gcry_pkalgo = map_pk_openpgp_to_gcry( sk->pubkey_algo ); + const int pkalgo = map_pk_openpgp_to_gcry (sk->pubkey_algo); /* Get the keygrip. */ err = hexkeygrip_from_pk (sk, &keygrip); if (err) goto leave; - /* Convert the data to an S-expression. */ - if (gcry_pkalgo == GCRY_PK_ELG ||gcry_pkalgo == GCRY_PK_ELG_E) + if (pkalgo == GCRY_PK_ELG || pkalgo == GCRY_PK_ELG_E) { if (!enc->data[0] || !enc->data[1]) err = gpg_error (GPG_ERR_BAD_MPI); @@ -164,7 +163,7 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) err = gcry_sexp_build (&s_data, NULL, "(enc-val(elg(a%m)(b%m)))", enc->data[0], enc->data[1]); } - else if (gcry_pkalgo == GCRY_PK_RSA || gcry_pkalgo == GCRY_PK_RSA_E) + else if (pkalgo == GCRY_PK_RSA || pkalgo == GCRY_PK_RSA_E) { if (!enc->data[0]) err = gpg_error (GPG_ERR_BAD_MPI); @@ -172,12 +171,12 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) err = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", enc->data[0]); } - else if (gcry_pkalgo == GCRY_PK_ECDH ) + else if (pkalgo == GCRY_PK_ECDH) { if (!enc->data[0] || !enc->data[1]) err = gpg_error (GPG_ERR_BAD_MPI); else - err = gcry_sexp_build (&s_data, NULL, "(enc-val(ecdh(a%m)(b%m)))", + err = gcry_sexp_build (&s_data, NULL, "(enc-val(ecdh(a%m)(b%m)))", enc->data[0], enc->data[1]); } else @@ -186,8 +185,9 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) if (err) goto leave; - fingerprint_from_pk( sk, fp, &fpn ); - assert( fpn == 20 ); + /* fixme: only needed for ECDH. Don't compute always. */ + fingerprint_from_pk (sk, fp, &fpn); + assert (fpn == 20); /* Decrypt. */ desc = gpg_format_keydesc (sk, 0, 1); @@ -222,12 +222,12 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) { gcry_mpi_t shared_mpi; gcry_mpi_t decoded; - + /* At the beginning the frame are the bytes of shared point MPI. */ err = gcry_mpi_scan (&shared_mpi, GCRYMPI_FMT_USG, frame, nframe, NULL); if (err) { - log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); + err = gpg_error (GPG_ERR_WRONG_SECKEY); goto leave; } @@ -247,13 +247,14 @@ get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid) /* Allow double padding for the benefit of DEK size concealment. Higher than this is wasteful. */ - if (frame[nframe-1] > 8*2 || nframe <= 8) + if (!nframe || frame[nframe-1] > 8*2 || nframe <= 8 + || frame[nframe-1] > nframe) { err = gpg_error (GPG_ERR_WRONG_SECKEY); - goto leave; + goto leave; } nframe -= frame[nframe-1]; /* Remove padding. */ - assert (n); /* (used just below) */ + assert (!n); /* (used just below) */ } else { diff --git a/g10/verify-stubs.c b/g10/verify-stubs.c deleted file mode 100644 index c4c657b..0000000 --- a/g10/verify-stubs.c +++ /dev/null @@ -1,31 +0,0 @@ -/* To satisfy the linker for the gpgv target - * Copyright (C) 2010 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * GnuPG is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include - -#include -#include "gpg.h" -#include "main.h" - -int -pk_ecc_keypair_gen (PKT_public_key **pk_out, int algo, int keygen_flags, - char **cache_nonce_addr, unsigned nbits) -{ - return GPG_ERR_NOT_IMPLEMENTED; -} ----------------------------------------------------------------------- Summary of changes: g10/ChangeLog | 27 ++++ g10/Makefile.am | 3 +- g10/ecdh.c | 316 ++++++++++++++++++----------------------------- g10/keygen.c | 348 +++++++++++++++++++++------------------------------- g10/main.h | 5 - g10/misc.c | 2 +- g10/pkglue.c | 70 +++++++++-- g10/pkglue.h | 13 ++- g10/pubkey-enc.c | 29 +++-- g10/verify-stubs.c | 31 ----- 10 files changed, 373 insertions(+), 471 deletions(-) delete mode 100644 g10/verify-stubs.c hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Tue Jan 25 21:37:43 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 25 Jan 2011 21:37:43 +0100 Subject: [git] GnuPG - branch, STABLE-BRANCH-2-0, updated. gnupg-2.0.16-32-gcb2f55e Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, STABLE-BRANCH-2-0 has been updated via cb2f55e9edae268d101e3e81f73a3498cfa68cf0 (commit) from abceb05d5432dcb25e25db908b1ce55ad964cf9e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit cb2f55e9edae268d101e3e81f73a3498cfa68cf0 Author: Werner Koch Date: Tue Jan 25 21:08:36 2011 +0100 Fix problem with unplugged card readers. From Grant Olsons's mail to gnupg-devel@: This is three-quarters NIIBE and one-quarter me, but I though it would be easier to have a single complete patch that applies to STABLE-BRANCH-2-0 than two patches floating around. This is basically NIIBE Yatuka's patch here: http://lists.gnupg.org/pipermail/gnupg-devel/2010-November/025828.html Plus another check that closes down the reader explicitly if we get a SW_HOST_NO_READER error, so that an unplugged reader doesn't hold onto the first slot, preventing us from getting to the active plugged reader. diff --git a/THANKS b/THANKS index 8e4c912..10e8631 100644 --- a/THANKS +++ b/THANKS @@ -92,6 +92,7 @@ Geoff Keating geoffk at ozemail.com.au Georg Schwarz georg.schwarz at iname.com Giampaolo Tomassoni g.tomassoni at libero.it Gilbert Fernandes gilbert_fernandes at hotmail.com +Grant Olson kgo at grant-olson net Greg Louis glouis at dynamicro.on.ca Greg Troxel gdt at ir.bbn.com Gregory Steuck steuck at iname.com diff --git a/scd/ChangeLog b/scd/ChangeLog index 419f9d4..5fb5909 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,10 @@ +2011-01-25 NIIBE Yutaka , + Grant Olson (wk) + + * command.c (do_reset, get_reader_slot) + (update_reader_status_file): Fix handling of the VALID flag for + unplugged readers. + 2010-03-17 Werner Koch * command.c (open_card): Return GPG_ERR_NOT_OPERATIONAL if no diff --git a/scd/command.c b/scd/command.c index e2cd1f5..28bc4df 100644 --- a/scd/command.c +++ b/scd/command.c @@ -309,7 +309,7 @@ do_reset (ctrl_t ctrl, int send_reset) { if (apdu_reset (slot)) { - slot_table[slot].reset_failed = 1; + slot_table[slot].valid = 0; } application_notify_card_reset (slot); } @@ -401,6 +401,14 @@ get_reader_slot (void) { int no_service_flag; ss->slot = apdu_open_reader (opt.reader_port, &no_service_flag); + + /* If we still don't have a slot, we have no readers. + Invalidate for now until a reader is attached. */ + if(ss->slot == -1) + { + ss->valid = 0; + } + if (no_service_flag) { log_info ("no card services - disabling scdaemon\n"); @@ -2192,6 +2200,8 @@ update_reader_status_file (int set_card_removed_flag) if (sw_apdu == SW_HOST_NO_READER) { /* Most likely the _reader_ has been unplugged. */ + apdu_close_reader (ss->slot); + ss->valid = 0; status = 0; changed = ss->changed; } ----------------------------------------------------------------------- Summary of changes: THANKS | 1 + scd/ChangeLog | 7 +++++++ scd/command.c | 12 +++++++++++- 3 files changed, 19 insertions(+), 1 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Tue Jan 25 22:23:44 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 25 Jan 2011 22:23:44 +0100 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta1-49-g576de6e Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, master has been updated via 576de6e539646f021dafff8d4e3327c115a51ad4 (commit) via ca2d3157656d542ceec50607d0b92f13542a0fe7 (commit) from 05a3f5639139c14d360da29141108a868fbc3071 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 576de6e539646f021dafff8d4e3327c115a51ad4 Author: Werner Koch Date: Tue Jan 25 22:03:16 2011 +0100 Fixed problem with unplugging card readers. From Grant Olsons's mail to gnupg-devel@: This is three-quarters NIIBE and one-quarter me, but I though it would be easier to have a single complete patch that applies to STABLE-BRANCH-2-0 than two patches floating around. This is basically NIIBE Yatuka's patch here: http://lists.gnupg.org/pipermail/gnupg-devel/2010-November/025828.html Plus another check that closes down the reader explicitly if we get a SW_HOST_NO_READER error, so that an unplugged reader doesn't hold onto the first slot, preventing us from getting to the active plugged reader. diff --git a/THANKS b/THANKS index c86fda3..b6dfc40 100644 --- a/THANKS +++ b/THANKS @@ -92,6 +92,7 @@ Geoff Keating geoffk at ozemail.com.au Georg Schwarz georg.schwarz at iname.com Giampaolo Tomassoni g.tomassoni at libero.it Gilbert Fernandes gilbert_fernandes at hotmail.com +Grant Olson kgo at grant-olson net Greg Louis glouis at dynamicro.on.ca Greg Troxel gdt at ir.bbn.com Gregory Steuck steuck at iname.com diff --git a/scd/ChangeLog b/scd/ChangeLog index d1e942a..c9f92b4 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,10 @@ +2011-01-25 NIIBE Yutaka , + Grant Olson (wk) + + * command.c (do_reset, get_reader_slot) + (update_reader_status_file): Fix handling of the VALID flag for + unplugged readers. + 2011-01-25 Werner Koch From 2.0 branch, 2010-03-17: diff --git a/scd/command.c b/scd/command.c index 36aff97..a44378d 100644 --- a/scd/command.c +++ b/scd/command.c @@ -309,7 +309,7 @@ do_reset (ctrl_t ctrl, int send_reset) { if (apdu_reset (slot)) { - slot_table[slot].reset_failed = 1; + slot_table[slot].valid = 0; } application_notify_card_reset (slot); } @@ -401,6 +401,14 @@ get_reader_slot (void) { int no_service_flag; ss->slot = apdu_open_reader (opt.reader_port, &no_service_flag); + + /* If we still don't have a slot, we have no readers. + Invalidate for now until a reader is attached. */ + if(ss->slot == -1) + { + ss->valid = 0; + } + if (no_service_flag) { log_info ("no card services - disabling scdaemon\n"); @@ -2190,6 +2198,8 @@ update_reader_status_file (int set_card_removed_flag) if (sw_apdu == SW_HOST_NO_READER) { /* Most likely the _reader_ has been unplugged. */ + apdu_close_reader(ss->slot); + ss->valid = 0; status = 0; changed = ss->changed; } commit ca2d3157656d542ceec50607d0b92f13542a0fe7 Author: Werner Koch Date: Mon May 3 11:10:49 2010 +0000 Detect non operational readers. Backport from 2.0. diff --git a/scd/ChangeLog b/scd/ChangeLog index 41a0f76..d1e942a 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,16 @@ +2011-01-25 Werner Koch + + From 2.0 branch, 2010-03-17: + + * command.c (open_card): Return GPG_ERR_NOT_OPERATIONAL if no + card services are available. + (get_reader_slot): Detect no services status. + (cmd_serialno): No reset if there are no services. + (scd_command_handler): Stop scdaemon in that case. + * apdu.c (pcsc_no_service): New. + (open_pcsc_reader_direct): Set it. + (apdu_open_reader): Add arg R_NO_SERVICE. + 2011-01-05 Werner Koch * ccid-driver.c (ccid_transceive_secure): Support the gnuk token. diff --git a/scd/apdu.c b/scd/apdu.c index 80c933e..dcb0e23 100644 --- a/scd/apdu.c +++ b/scd/apdu.c @@ -304,6 +304,9 @@ long (* DLSTDCALL pcsc_transmit) (unsigned long card, long (* DLSTDCALL pcsc_set_timeout) (unsigned long context, unsigned long timeout); +/* Flag set if PC/SC returned the no-service error. */ +static int pcsc_no_service; + /* Prototypes. */ static int pcsc_get_status (int slot, unsigned int *status); @@ -1504,8 +1507,11 @@ open_pcsc_reader_direct (const char *portstr) log_error ("pcsc_establish_context failed: %s (0x%lx)\n", pcsc_error_string (err), err); reader_table[slot].used = 0; + if (err == 0x8010001d) + pcsc_no_service = 1; return -1; } + pcsc_no_service = 0; err = pcsc_list_readers (reader_table[slot].pcsc.context, NULL, NULL, &nreader); @@ -2338,14 +2344,18 @@ unlock_slot (int slot) error. If PORTSTR is NULL we default to a suitable port (for ctAPI: the first USB reader. For PC/SC the first listed reader). */ int -apdu_open_reader (const char *portstr) +apdu_open_reader (const char *portstr, int *r_no_service) { static int pcsc_api_loaded, ct_api_loaded; + int slot; + + if (r_no_service) + *r_no_service = 0; #ifdef HAVE_LIBUSB if (!opt.disable_ccid) { - int slot, i; + int i; const char *s; slot = open_ccid_reader (portstr); @@ -2475,7 +2485,11 @@ apdu_open_reader (const char *portstr) pcsc_api_loaded = 1; } - return open_pcsc_reader (portstr); + slot = open_pcsc_reader (portstr); + if (slot == -1 && r_no_service && pcsc_no_service) + *r_no_service = 1; + + return slot; } diff --git a/scd/apdu.h b/scd/apdu.h index c47dea8..d79f8b4 100644 --- a/scd/apdu.h +++ b/scd/apdu.h @@ -80,8 +80,8 @@ enum { #define APDU_CARD_ACTIVE (4) /* Card is active. */ -/* Note , that apdu_open_reader returns no status word but -1 on error. */ -int apdu_open_reader (const char *portstr); +/* Note, that apdu_open_reader returns no status word but -1 on error. */ +int apdu_open_reader (const char *portstr, int *r_no_service); int apdu_open_remote_reader (const char *portstr, const unsigned char *cookie, size_t length, int (*readfnc) (void *opaque, diff --git a/scd/command.c b/scd/command.c index fa1d46c..36aff97 100644 --- a/scd/command.c +++ b/scd/command.c @@ -70,6 +70,10 @@ && (c)->reader_slot == locked_session->ctrl_backlink->reader_slot) +/* Flag indicating that the reader has been disabled. */ +static int reader_disabled; + + /* This structure is used to keep track of open readers (slots). */ struct slot_status_s { @@ -394,7 +398,15 @@ get_reader_slot (void) /* Try to open the reader. */ if (ss->slot == -1) - ss->slot = apdu_open_reader (opt.reader_port); + { + int no_service_flag; + ss->slot = apdu_open_reader (opt.reader_port, &no_service_flag); + if (no_service_flag) + { + log_info ("no card services - disabling scdaemon\n"); + reader_disabled = 1; + } + } /* Return the slot_table index. */ return 0; @@ -409,6 +421,9 @@ open_card (ctrl_t ctrl, const char *apptype) gpg_error_t err; int slot; + if (reader_disabled) + return gpg_error (GPG_ERR_NOT_OPERATIONAL); + /* If we ever got a card not present error code, return that. Only the SERIALNO command and a reset are able to clear from that state. */ @@ -441,7 +456,7 @@ open_card (ctrl_t ctrl, const char *apptype) slot = get_reader_slot (); ctrl->reader_slot = slot; if (slot == -1) - err = gpg_error (GPG_ERR_CARD); + err = gpg_error (reader_disabled? GPG_ERR_NOT_OPERATIONAL: GPG_ERR_CARD); else { /* Fixme: We should move the apdu_connect call to @@ -495,7 +510,7 @@ cmd_serialno (assuan_context_t ctx, char *line) time_t stamp; /* Clear the remove flag so that the open_card is able to reread it. */ - if (ctrl->server_local->card_removed) + if (!reader_disabled && ctrl->server_local->card_removed) { if ( IS_LOCKED (ctrl) ) return gpg_error (GPG_ERR_LOCKED); @@ -1993,7 +2008,7 @@ scd_command_handler (ctrl_t ctrl, int fd) BUG (); sl->next_session = ctrl->server_local->next_session; } - stopme = ctrl->server_local->stopme; + stopme = ctrl->server_local->stopme || reader_disabled; xfree (ctrl->server_local); ctrl->server_local = NULL; diff --git a/scd/sc-copykeys.c b/scd/sc-copykeys.c index 615e4b2..b863b01 100644 --- a/scd/sc-copykeys.c +++ b/scd/sc-copykeys.c @@ -139,7 +139,7 @@ main (int argc, char **argv ) if (argc != 1) usage (1); - slot = apdu_open_reader (reader_port); + slot = apdu_open_reader (reader_port, NULL); if (slot == -1) exit (1); if (apdu_connect (slot)) ----------------------------------------------------------------------- Summary of changes: THANKS | 1 + scd/ChangeLog | 20 ++++++++++++++++++++ scd/apdu.c | 20 +++++++++++++++++--- scd/apdu.h | 4 ++-- scd/command.c | 35 ++++++++++++++++++++++++++++++----- scd/sc-copykeys.c | 2 +- 6 files changed, 71 insertions(+), 11 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Wed Jan 26 18:09:58 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 26 Jan 2011 18:09:58 +0100 Subject: [git] GnuPG - branch, ECC-INTEGRATION-2-1, updated. gnupg-2.1.0beta1-63-g358afc0 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, ECC-INTEGRATION-2-1 has been updated via 358afc0dc8980d5ae0cb700efbb61499625a4625 (commit) from d879c287ac1da7990c97b911018d63410c60433c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 358afc0dc8980d5ae0cb700efbb61499625a4625 Author: Werner Koch Date: Wed Jan 26 17:17:43 2011 +0100 Function name cleanups Also nuked some trailing spaces. diff --git a/g10/ChangeLog b/g10/ChangeLog index 9e1aa01..b276015 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,15 @@ +2011-01-26 Werner Koch + + * misc.c (ecdsa_qbits_from_Q): Use unsigned int. + + * misc.c (iobuf_read_size_body): Move and rename to .. + * parse-packet.c (read_size_body): .. here. Make static. + * misc.c (iobuf_write_size_body_mpi): Move and rename to .. + * build-packet.c (write_size_body_mpi): .. here. + (iobuf_name_oid_write, ecdh_kek_params_write, ecdh_esk_write): + Remove macros. Replace users by direct calls to + write_size_body_mpi. + 2011-01-25 Werner Koch * ecdh.c (pk_ecdh_default_params_to_mpi): Remove. diff --git a/g10/build-packet.c b/g10/build-packet.c index d138e06..e2bbdb5 100644 --- a/g10/build-packet.c +++ b/g10/build-packet.c @@ -178,17 +178,44 @@ mpi_write (iobuf_t out, gcry_mpi_t a) return rc; } -/* Write the name OID, encoded as an mpi, to OUT. The format of the - * content of the MPI is one byte LEN, following by LEN bytes that are - * DER representation of an ASN.1 OID. This is true for each of the 3 - * following functions. */ -#define iobuf_name_oid_write iobuf_write_size_body_mpi -/* Write the value of KEK fields for ECDH. */ -#define ecdh_kek_params_write iobuf_write_size_body_mpi +/* + * Write a special size+body mpi A, to OUT. The format of the content + * of the MPI is one byte LEN, following by LEN bytes. + */ +gpg_error_t +write_size_body_mpi (iobuf_t out, gcry_mpi_t a) +{ + gpg_error_t err; + byte buffer[256]; /* Fixed buffer for a public parameter, max possible */ + size_t nbytes = (mpi_get_nbits (a)+7)/8; + + if (nbytes > sizeof(buffer)) + { + log_error("mpi with size+body is too large (%u bytes)\n", nbytes); + return gpg_error (GPG_ERR_TOO_LARGE); + } -/* Write the value of encrypted filed for ECDH. */ -#define ecdh_esk_write iobuf_write_size_body_mpi + err = gcry_mpi_print (GCRYMPI_FMT_USG, buffer, sizeof(buffer), &nbytes, a); + if (err) + { + log_error ("failed to exported size+body mpi\n"); + return err; + } + if (nbytes < 2 || buffer[0] != nbytes-1) + { + if (nbytes > 2) + log_error ("internal size mismatch in mpi size+body: " + "%02x != %02x (other bytes: %02x %02x ... %02x %02x)\n", + buffer[0], nbytes-1, buffer[1], buffer[2], buffer[nbytes-2], + buffer[nbytes-1]); + else + log_error ("internal size mismatch in mpi size+body: " + "only %d bytes\n", nbytes); + return gpg_error (GPG_ERR_INV_DATA); + } + return iobuf_write (out, buffer, nbytes); +} /* Calculate the length of a packet described by PKT. */ @@ -228,11 +255,11 @@ calc_packet_length( PACKET *pkt ) static void write_fake_data (IOBUF out, gcry_mpi_t a) { - if (a) + if (a) { unsigned int n; void *p; - + p = gcry_mpi_get_opaque ( a, &n ); iobuf_write (out, p, (n+7)/8 ); } @@ -281,18 +308,18 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) ndays = 0; write_16(a, ndays); } - + 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 (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, pk->pkey[0]); goto leave; @@ -305,7 +332,7 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) || pk->pubkey_algo == PUBKEY_ALGO_ECDH) { /* Write DER of OID with preceeding length byte. */ - err = iobuf_name_oid_write (a, pk->pkey[0]); + err = write_size_body_mpi (a, pk->pkey[0]); if (err) goto leave; /* Write point Q, the public key. */ @@ -316,7 +343,7 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) /* Write one more public field for ECDH. */ if (pk->pubkey_algo == PUBKEY_ALGO_ECDH) { - err = ecdh_kek_params_write(a,pk->pkey[2]); + err = write_size_body_mpi (a, pk->pkey[2]); if (err) goto leave; } @@ -328,14 +355,14 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) goto leave; } - + if (pk->seckey_info) { /* 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) + if (ski->is_protected) { if ( is_RSA (pk->pubkey_algo) && pk->version < 4 && !ski->s2k.mode ) { @@ -355,12 +382,12 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) 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, 101); iobuf_put (a, ski->s2k.hash_algo); iobuf_write (a, "GNU", 3 ); iobuf_put (a, ski->s2k.mode - 1000); } - else + else { iobuf_put (a, ski->s2k.mode); iobuf_put (a, ski->s2k.hash_algo); @@ -370,7 +397,7 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) iobuf_write (a, ski->s2k.salt, 8); if (ski->s2k.mode == 3) - iobuf_put (a, ski->s2k.count); + 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) @@ -381,10 +408,10 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) iobuf_put (a, 0 ); if (ski->s2k.mode == 1001) - ; /* GnuPG extension - don't write a secret key at all. */ + ; /* GnuPG extension - don't write a secret key at all. */ else if (ski->s2k.mode == 1002) - { - /* GnuPG extension - divert to OpenPGP smartcard. */ + { + /* 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. */ @@ -395,19 +422,19 @@ do_key (iobuf_t out, int ctb, PKT_public_key *pk) /* 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) + else if (ski->is_protected) { /* The secret key is protected the old v4 way. */ - for ( ; i < nskey; i++ ) + for ( ; i < nskey; i++ ) { byte *p; unsigned int ndatabits; - + assert (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE)); p = gcry_mpi_get_opaque (pk->pkey[i], &ndatabits); iobuf_write (a, p, (ndatabits+7)/8); @@ -476,9 +503,9 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) int rc = 0; int n, i; IOBUF a = iobuf_temp(); - + write_version( a, ctb ); - if ( enc->throw_keyid ) + if ( enc->throw_keyid ) { write_32(a, 0 ); /* Don't tell Eve who can decrypt the message. */ write_32(a, 0 ); @@ -500,7 +527,7 @@ do_pubkey_enc( IOBUF out, int ctb, PKT_pubkey_enc *enc ) assert (n == 2); rc = mpi_write (a, enc->data[0]); if (!rc) - rc = ecdh_esk_write (a, enc->data[1]); + rc = write_size_body_mpi (a, enc->data[1]); } else { @@ -545,7 +572,7 @@ do_plaintext( IOBUF out, int ctb, PKT_plaintext *pt ) for(i=0; i < pt->namelen; i++ ) iobuf_put(out, pt->name[i] ); rc = write_32(out, pt->timestamp ); - if (rc) + if (rc) return rc; n = 0; @@ -661,7 +688,7 @@ delete_sig_subpkt (subpktarea_t *area, sigsubpkttype_t reqtype ) } if( buflen < n ) break; - + type = *buffer & 0x7f; if( type == reqtype ) { buffer++; @@ -695,7 +722,7 @@ delete_sig_subpkt (subpktarea_t *area, sigsubpkttype_t reqtype ) * Note: All pointers into sig->[un]hashed (e.g. returned by * parse_sig_subpkt) are not valid after a call to this function. The * data to put into the subpaket should be in a buffer with a length - * of buflen. + * of buflen. */ void build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, @@ -798,7 +825,7 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, case SIGSUBPKT_SIGNATURE: hashed = 0; break; - default: + default: hashed = 1; break; } @@ -849,7 +876,7 @@ build_sig_subpkt (PKT_signature *sig, sigsubpkttype_t type, memcpy (p, buffer, buflen); } - if (hashed) + if (hashed) sig->hashed = newarea; else sig->unhashed = newarea; @@ -1135,7 +1162,7 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig ) if ( sig->version < 4 ) iobuf_put (a, 5 ); /* Constant */ iobuf_put (a, sig->sig_class ); - if ( sig->version < 4 ) + if ( sig->version < 4 ) { write_32(a, sig->timestamp ); write_32(a, sig->keyid[0] ); @@ -1143,7 +1170,7 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig ) } iobuf_put(a, sig->pubkey_algo ); iobuf_put(a, sig->digest_algo ); - if ( sig->version >= 4 ) + if ( sig->version >= 4 ) { size_t nn; /* Timestamp and keyid must have been packed into the subpackets diff --git a/g10/ecdh.c b/g10/ecdh.c index 71c32fd..95bd866 100644 --- a/g10/ecdh.c +++ b/g10/ecdh.c @@ -161,7 +161,7 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, */ { IOBUF obuf = iobuf_temp(); - err = iobuf_write_size_body_mpi ( obuf, pkey[2] ); /* KEK params */ + err = write_size_body_mpi (obuf, pkey[2]); /* KEK params */ kdf_params_size = iobuf_temp_to_buffer (obuf, kdf_params, sizeof(kdf_params)); @@ -198,11 +198,11 @@ pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, obuf = iobuf_temp(); /* variable-length field 1, curve name OID */ - err = iobuf_write_size_body_mpi ( obuf, pkey[0] ); + err = write_size_body_mpi (obuf, pkey[0]); /* fixed-length field 2 */ iobuf_put (obuf, PUBKEY_ALGO_ECDH); /* variable-length field 3, KDF params */ - err = (err ? err : iobuf_write_size_body_mpi ( obuf, pkey[2] )); + err = (err ? err : write_size_body_mpi ( obuf, pkey[2] )); /* fixed-length field 4 */ iobuf_write (obuf, "Anonymous Sender ", 20); /* fixed-length field 5, recipient fp */ diff --git a/g10/main.h b/g10/main.h index ea1ac2e..4cec61f 100644 --- a/g10/main.h +++ b/g10/main.h @@ -161,11 +161,7 @@ int pubkey_get_nsig( int algo ); int pubkey_get_nenc( int algo ); unsigned int pubkey_nbits( int algo, gcry_mpi_t *pkey ); int mpi_print (estream_t stream, gcry_mpi_t a, int mode); -int iobuf_write_size_body_mpi (iobuf_t out, gcry_mpi_t a); -int iobuf_read_size_body (iobuf_t inp, byte *body, int body_max_size, - int pktlen, gcry_mpi_t *out); - -int ecdsa_qbits_from_Q( int qbits ); +unsigned int ecdsa_qbits_from_Q (unsigned int qbits); /*-- status.c --*/ void set_status_fd ( int fd ); diff --git a/g10/misc.c b/g10/misc.c index fd00ec6..dc2f73b 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -1459,7 +1459,6 @@ pubkey_nbits( int algo, gcry_mpi_t *key ) -/* FIXME: Use gcry_mpi_print directly. */ int mpi_print (estream_t fp, gcry_mpi_t a, int mode) { @@ -1487,98 +1486,15 @@ mpi_print (estream_t fp, gcry_mpi_t a, int mode) } -/* - * Write a special size+body mpi A, to OUT. The format of the content - * of the MPI is one byte LEN, following by LEN bytes. - */ -/* FIXME: Rename this function: it is not in iobuf.c */ -int -iobuf_write_size_body_mpi (iobuf_t out, gcry_mpi_t a) -{ - byte buffer[256]; /* Fixed buffer for a public parameter, max possible */ - size_t nbytes = (mpi_get_nbits (a)+7)/8; - int rc; - - if( nbytes > sizeof(buffer) ) { - log_error("mpi with size+body is too large (%u bytes)\n", nbytes); - return gpg_error (GPG_ERR_TOO_LARGE); - } - - rc = gcry_mpi_print (GCRYMPI_FMT_USG, buffer, sizeof(buffer), &nbytes, a); - if( rc ) { - log_error("Failed to exported size+body mpi\n"); - return rc; - } - if( nbytes < 2 || buffer[0] != nbytes-1 ) { - if( nbytes > 2 ) - log_error("Internal size mismatch in mpi size+body: %02x != %02x (other bytes: %02x %02x ... %02x %02x)\n", - buffer[0], nbytes-1, buffer[1], buffer[2], buffer[nbytes-2], buffer[nbytes-1]); - else - log_error("Internal size mismatch in mpi size+body: only %d bytes\n", nbytes ); - return gpg_error (GPG_ERR_INV_DATA); - } - return iobuf_write( out, buffer, nbytes ); -} - - -/* - * Read a special size+body from inp into body[body_max_size] and - * return it in a buffer and as MPI. On success the number of - * consumed bytes will body[0]+1. The format of the content of the - * returned MPI is one byte LEN, following by LEN bytes. Caller is - * expected to pre-allocate fixed-size 255 byte buffer (or smaller - * when appropriate). - */ -/* FIXME: Rename this function: it is not in iobuf.c */ -int -iobuf_read_size_body (iobuf_t inp, byte *body, int body_max_size, - int pktlen, gcry_mpi_t *out ) -{ - unsigned n; - int rc; - gcry_mpi_t result; - - *out = NULL; - - if( (n = iobuf_readbyte(inp)) == -1 ) - { - return G10ERR_INVALID_PACKET; - } - if ( n >= body_max_size || n < 2) - { - log_error("invalid size+body field\n"); - return G10ERR_INVALID_PACKET; - } - body[0] = n; - if ((n = iobuf_read(inp, body+1, n)) == -1) - { - log_error("invalid size+body field\n"); - return G10ERR_INVALID_PACKET; - } - if (n+1 > pktlen) - { - log_error("size+body field is larger than the packet\n"); - return G10ERR_INVALID_PACKET; - } - rc = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, body, n+1, NULL); - if (rc) - log_fatal ("mpi_scan failed: %s\n", gpg_strerror (rc)); - - *out = result; - - return rc; -} - - /* pkey[1] or skey[1] is Q for ECDSA, which is an uncompressed point, i.e. 04 */ -int -ecdsa_qbits_from_Q (int qbits ) +unsigned int +ecdsa_qbits_from_Q (unsigned int qbits) { if ((qbits%8) > 3) { - log_error(_("ECDSA public key is expected to be in SEC encoding " - "multiple of 8 bits\n")); + log_error (_("ECDSA public key is expected to be in SEC encoding " + "multiple of 8 bits\n")); return 0; } qbits -= qbits%8; diff --git a/g10/packet.h b/g10/packet.h index 541462a..d06c4c7 100644 --- a/g10/packet.h +++ b/g10/packet.h @@ -444,6 +444,7 @@ PACKET *create_gpg_control ( ctrlpkttype_t type, /*-- build-packet.c --*/ int build_packet( iobuf_t inp, PACKET *pkt ); +gpg_error_t write_size_body_mpi (iobuf_t out, gcry_mpi_t a); u32 calc_packet_length( PACKET *pkt ); void build_sig_subpkt( PKT_signature *sig, sigsubpkttype_t type, const byte *buffer, size_t buflen ); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index 334a9a8..a0844c7 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -741,6 +741,55 @@ read_rest (IOBUF inp, size_t pktlen, int partial) } +/* + * Read a special size+body from inp into body[body_max_size] and + * return it in a buffer and as MPI. On success the number of + * consumed bytes will body[0]+1. The format of the content of the + * returned MPI is one byte LEN, following by LEN bytes. Caller is + * expected to pre-allocate fixed-size 255 byte buffer (or smaller + * when appropriate). + */ +static int +read_size_body (iobuf_t inp, byte *body, int body_max_size, + int pktlen, gcry_mpi_t *out ) +{ + unsigned int n; + int rc; + gcry_mpi_t result; + + *out = NULL; + + if( (n = iobuf_readbyte(inp)) == -1 ) + { + return G10ERR_INVALID_PACKET; + } + if ( n >= body_max_size || n < 2) + { + log_error("invalid size+body field\n"); + return G10ERR_INVALID_PACKET; + } + body[0] = n; + if ((n = iobuf_read(inp, body+1, n)) == -1) + { + log_error("invalid size+body field\n"); + return G10ERR_INVALID_PACKET; + } + if (n+1 > pktlen) + { + log_error("size+body field is larger than the packet\n"); + return G10ERR_INVALID_PACKET; + } + rc = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, body, n+1, NULL); + if (rc) + log_fatal ("mpi_scan failed: %s\n", gpg_strerror (rc)); + + *out = result; + + return rc; +} + + +/* Parse a marker packet. */ static int parse_marker (IOBUF inp, int pkttype, unsigned long pktlen) { @@ -947,8 +996,8 @@ parse_pubkeyenc (IOBUF inp, int pkttype, unsigned long pktlen, n = pktlen; k->data[0] = mpi_read (inp, &n, 0); pktlen -= n; - rc = iobuf_read_size_body (inp, encr_buf, sizeof(encr_buf), - pktlen, k->data+1); + rc = read_size_body (inp, encr_buf, sizeof(encr_buf), + pktlen, k->data+1); if (rc) goto leave; @@ -1958,8 +2007,8 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, /* FIXME: The code in this function ignores the errors. */ byte name_oid[256]; - err = iobuf_read_size_body (inp, name_oid, sizeof(name_oid), - pktlen, pk->pkey+0); + err = read_size_body (inp, name_oid, sizeof(name_oid), + pktlen, pk->pkey+0); if (err) goto leave; n = name_oid[0]; @@ -1984,8 +2033,8 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, if (algorithm == PUBKEY_ALGO_ECDH) { /* (NAMEOID holds the KEK params.) */ - err = iobuf_read_size_body (inp, name_oid, sizeof(name_oid), - pktlen, pk->pkey+2); + err = read_size_body (inp, name_oid, sizeof(name_oid), + pktlen, pk->pkey+2); if (err) goto leave; n = name_oid[0]; ----------------------------------------------------------------------- Summary of changes: g10/ChangeLog | 12 ++++++ g10/build-packet.c | 105 ++++++++++++++++++++++++++++++++------------------- g10/ecdh.c | 6 +- g10/main.h | 6 +-- g10/misc.c | 92 ++------------------------------------------- g10/packet.h | 1 + g10/parse-packet.c | 61 +++++++++++++++++++++++++++--- 7 files changed, 142 insertions(+), 141 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Wed Jan 26 18:09:58 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 26 Jan 2011 18:09:58 +0100 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta1-50-gf9688d8 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU Privacy Guard". The branch, master has been updated via f9688d859af326d6e3a46920974e06369dc0ec85 (commit) from 576de6e539646f021dafff8d4e3327c115a51ad4 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit f9688d859af326d6e3a46920974e06369dc0ec85 Author: Werner Koch Date: Wed Jan 26 17:19:39 2011 +0100 Add gitattributes diff --git a/po/.gitattributes b/po/.gitattributes new file mode 100644 index 0000000..17b178c --- /dev/null +++ b/po/.gitattributes @@ -0,0 +1,7 @@ +# You should add +#[filter "cleanpo"] +# clean = "awk '/^\"POT-Creation-Date:/&&!s{s=1;next};!/^#: /{print}'" +# to your config file. + +/??.po filter=cleanpo +/??_??.po filter=cleanpo ----------------------------------------------------------------------- Summary of changes: po/.gitattributes | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) create mode 100644 po/.gitattributes hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Fri Jan 28 17:35:36 2011 From: cvs at cvs.gnupg.org (by Andreas Holzammer) Date: Fri, 28 Jan 2011 17:35:36 +0100 Subject: [git] Wincetools - branch, kdepimcetools, updated. 8ab1608b4c98ac0fe9f14070c574523df01d8f84 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "UNNAMED PROJECT". The branch, kdepimcetools has been updated via 8ab1608b4c98ac0fe9f14070c574523df01d8f84 (commit) from 78287e3f2742c170d89ddcb448cbe14506e7c0dd (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 8ab1608b4c98ac0fe9f14070c574523df01d8f84 Author: Andreas Holzammer Date: Fri Jan 28 17:15:23 2011 +0100 dont load the executables high anymore Because they fit into the process slot and then the system can do pageing diff --git a/loader/himemce.c b/loader/himemce.c index 6593b41..ba388b9 100644 --- a/loader/himemce.c +++ b/loader/himemce.c @@ -63,7 +63,6 @@ main (int argc, char *argv[]) WCHAR *cmdline; BOOL ret; - int result = 0; SetCursor( LoadCursor( NULL, IDC_WAIT ) ); app_name = get_app_name (); @@ -74,12 +73,12 @@ main (int argc, char *argv[]) /* Note that this does not spawn a new process, but just calls into the startup function of the app eventually, and returns with its exit code. */ - ret = MyCreateProcessW (app_name, cmdline, &result); + ret = CreateProcess (app_name, cmdline, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, NULL, NULL); if (! ret) { ERR ("starting %S failed: %i\n", app_name, GetLastError()); return 1; } - return result; + return 0; } diff --git a/loader/splashscreen.cpp b/loader/splashscreen.cpp index 13342fd..d6f3094 100644 --- a/loader/splashscreen.cpp +++ b/loader/splashscreen.cpp @@ -2,10 +2,7 @@ #include #include "himemce.h" -// Global Bitmap variable -HBITMAP hbm; - -const wchar_t *szTitle = L"Kontact Mobile"; // title bar text +const wchar_t *szTitle = L"Kontact Touch"; // title bar text const wchar_t *szWindowClass = L"SplashScreen"; // main window class name //Prototype of the main function from the loader @@ -27,75 +24,6 @@ BOOL RotateTo270Degrees() return true; } -// Load Splashscreen from resource dll -BOOL onCreate( - HWND hwnd) -{ - // Load Splashscreen dll - HINSTANCE hinst = LoadLibrary(L"splashscreen.dll"); - - if (!hinst) { - printf("failed to load splashscreen dll!\n"); - return false; - } - hbm = LoadBitmap(hinst,MAKEINTRESOURCE(101)); - - return true; -} - -// Clean up -void onDestroy( - HWND hwnd) -{ - DeleteObject(hbm); - - PostQuitMessage(0); -} - -void onPaint( - HWND hwnd) -{ - PAINTSTRUCT ps; - HDC hdc = BeginPaint(hwnd,&ps); - - HDC hdcMem = CreateCompatibleDC(NULL); - SelectObject(hdcMem, hbm); - - BITMAP bm; - GetObject(hbm,sizeof(bm),&bm); - - BitBlt(hdc,0,0,bm.bmWidth,bm.bmHeight,hdcMem,0,0,SRCCOPY); - - DeleteDC(hdcMem); - - EndPaint(hwnd,&ps); -} - - -LRESULT CALLBACK windowProc( - HWND hwnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam) -{ - switch(uMsg) - { - case WM_CREATE: - onCreate(hwnd); - break; - case WM_DESTROY: - onDestroy(hwnd); - break; - case WM_PAINT: - onPaint(hwnd); - break; - case WM_SETTINGCHANGE: - RotateTo270Degrees(); - break; - } - return DefWindowProc(hwnd,uMsg,wParam,lParam); -} - /* Restore a Window of a process based on the filename * of this process. With some special Case handling for * Kontact-Mobile @@ -120,11 +48,11 @@ restore_existing_window( const wchar_t * filename ) } TRACE("BASENAME of %S \n is : %S \n", filename, basename); - c = L'-'; + c = L'.'; p = wcsrchr(filename, c); if (! p ) { - TRACE("File extension -real.exe could not be found\n"); + TRACE("File extension .exe could not be found\n"); return false; } *p = L'\0'; @@ -157,22 +85,6 @@ restore_existing_window( const wchar_t * filename ) return false; } -void registerClass( - HINSTANCE hInstance) -{ - WNDCLASS wc = { - CS_NOCLOSE, - windowProc, - 0,0, - hInstance, - NULL, - NULL, - (HBRUSH) GetStockObject(WHITE_BRUSH), - NULL, - szWindowClass - }; - RegisterClass(&wc); -} int WINAPI WinMain( HINSTANCE hInstance, @@ -190,29 +102,12 @@ int WINAPI WinMain( return 0; } - // If the splashscreen window is already loaded just show it + // Show splashscreen hwnd = FindWindow(szWindowClass, szTitle); if (hwnd) { ::ShowWindow( hwnd, SW_SHOW ); SetForegroundWindow( hwnd ); SHFullScreen(hwnd, SHFS_HIDETASKBAR | SHFS_HIDESTARTICON | SHFS_HIDESIPBUTTON); - } else { - registerClass(hInstance); - - hwnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE, - 0, 0, 0, 0, NULL, NULL, hInstance, NULL); - - SHFullScreen(hwnd, SHFS_HIDETASKBAR | SHFS_HIDESTARTICON | SHFS_HIDESIPBUTTON); - - RECT rc; - // Next resize the main window to the size of the screen. - SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); - MoveWindow(hwnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE); - - SetForegroundWindow(hwnd); - - ShowWindow(hwnd,nCmdShow); - UpdateWindow(hwnd); } //Call the loaders main function ----------------------------------------------------------------------- Summary of changes: loader/himemce.c | 5 +- loader/splashscreen.cpp | 113 ++--------------------------------------------- 2 files changed, 6 insertions(+), 112 deletions(-) hooks/post-receive -- UNNAMED PROJECT http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jan 31 10:02:20 2011 From: cvs at cvs.gnupg.org (by Andreas Holzammer) Date: Mon, 31 Jan 2011 10:02:20 +0100 Subject: [git] Wincetools - branch, kdepimcetools, updated. 8691bd49a7c88aa8909e395aec3ba9d75f8db098 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "UNNAMED PROJECT". The branch, kdepimcetools has been updated via 8691bd49a7c88aa8909e395aec3ba9d75f8db098 (commit) from 8ab1608b4c98ac0fe9f14070c574523df01d8f84 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 8691bd49a7c88aa8909e395aec3ba9d75f8db098 Author: Andreas Holzammer Date: Mon Jan 31 09:41:53 2011 +0100 use for kleopatra also the laoder diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 73ad9f8..e384053 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -52,6 +52,14 @@ add_executable(tasks-mobile-loader WIN32 himemce.c compat.c target_link_libraries(tasks-mobile-loader aygshell) install(TARGETS tasks-mobile-loader DESTINATION bin) +add_executable(kleopatra-loader WIN32 himemce.c compat.c + my_winternl.h + kernel32_kernel_private.h kernel32_process.c kernel32_module.c + ntdll_error.c ntdll_loader.c ntdll_virtual.c + server_protocol.h server_mapping.c splashscreen.cpp kleopatra.rc) +target_link_libraries(kleopatra-loader aygshell) +install(TARGETS kleopatra-loader DESTINATION bin) + add_library(splashscreen SHARED dummy.cpp splashscreen.rc) SET_TARGET_PROPERTIES(splashscreen PROPERTIES LINK_FLAGS /NOENTRY) install(TARGETS splashscreen DESTINATION bin) diff --git a/loader/icons/kleopatra.ico b/loader/icons/kleopatra.ico new file mode 100644 index 0000000..81f1890 Binary files /dev/null and b/loader/icons/kleopatra.ico differ diff --git a/loader/kleopatra.rc b/loader/kleopatra.rc new file mode 100644 index 0000000..72e257b --- /dev/null +++ b/loader/kleopatra.rc @@ -0,0 +1 @@ +KLEOPATRA_MOBILE_ICON ICON "icons\kleopatra.ico" ----------------------------------------------------------------------- Summary of changes: loader/CMakeLists.txt | 8 ++++++++ loader/icons/kleopatra.ico | Bin 0 -> 16958 bytes loader/kleopatra.rc | 1 + 3 files changed, 9 insertions(+), 0 deletions(-) create mode 100644 loader/icons/kleopatra.ico create mode 100644 loader/kleopatra.rc hooks/post-receive -- UNNAMED PROJECT http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jan 31 11:15:11 2011 From: cvs at cvs.gnupg.org (by Andreas Holzammer) Date: Mon, 31 Jan 2011 11:15:11 +0100 Subject: [git] Wincetools - branch, kdepimcetools, updated. 8e14d6599a1d1a9a21a6f4c1a7f82cc55fcae369 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "UNNAMED PROJECT". The branch, kdepimcetools has been updated via 8e14d6599a1d1a9a21a6f4c1a7f82cc55fcae369 (commit) from 8691bd49a7c88aa8909e395aec3ba9d75f8db098 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 8e14d6599a1d1a9a21a6f4c1a7f82cc55fcae369 Author: Andreas Holzammer Date: Mon Jan 31 10:52:52 2011 +0100 make the loading to the high mem optional diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index e384053..f9a166f 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -17,6 +17,7 @@ add_executable(kmail-mobile-loader WIN32 himemce.c compat.c kernel32_kernel_private.h kernel32_process.c kernel32_module.c ntdll_error.c ntdll_loader.c ntdll_virtual.c server_protocol.h server_mapping.c splashscreen.cpp kmail-mobile.rc) +set_target_properties(kmail-mobile-loader PROPERTIES COMPILE_FLAGS -DUSE_LOADER) target_link_libraries(kmail-mobile-loader aygshell) install(TARGETS kmail-mobile-loader DESTINATION bin) @@ -26,6 +27,7 @@ add_executable(notes-mobile-loader WIN32 himemce.c compat.c ntdll_error.c ntdll_loader.c ntdll_virtual.c server_protocol.h server_mapping.c splashscreen.cpp notes-mobile.rc) target_link_libraries(notes-mobile-loader aygshell) +set_target_properties(notes-mobile-loader PROPERTIES COMPILE_FLAGS -DUSE_LOADER) install(TARGETS notes-mobile-loader DESTINATION bin) add_executable(kaddressbook-mobile-loader WIN32 himemce.c compat.c @@ -34,6 +36,7 @@ add_executable(kaddressbook-mobile-loader WIN32 himemce.c compat.c ntdll_error.c ntdll_loader.c ntdll_virtual.c server_protocol.h server_mapping.c splashscreen.cpp kaddressbook-mobile.rc) target_link_libraries(kaddressbook-mobile-loader aygshell) +set_target_properties(kaddressbook-mobile-loader PROPERTIES COMPILE_FLAGS -DUSE_LOADER) install(TARGETS kaddressbook-mobile-loader DESTINATION bin) add_executable(korganizer-mobile-loader WIN32 himemce.c compat.c @@ -42,6 +45,7 @@ add_executable(korganizer-mobile-loader WIN32 himemce.c compat.c ntdll_error.c ntdll_loader.c ntdll_virtual.c server_protocol.h server_mapping.c splashscreen.cpp korganizer-mobile.rc) target_link_libraries(korganizer-mobile-loader aygshell) +set_target_properties(korganizer-mobile-loader PROPERTIES COMPILE_FLAGS -DUSE_LOADER) install(TARGETS korganizer-mobile-loader DESTINATION bin) add_executable(tasks-mobile-loader WIN32 himemce.c compat.c @@ -50,6 +54,7 @@ add_executable(tasks-mobile-loader WIN32 himemce.c compat.c ntdll_error.c ntdll_loader.c ntdll_virtual.c server_protocol.h server_mapping.c splashscreen.cpp tasks-mobile.rc) target_link_libraries(tasks-mobile-loader aygshell) +set_target_properties(tasks-mobile-loader PROPERTIES COMPILE_FLAGS -DUSE_LOADER) install(TARGETS tasks-mobile-loader DESTINATION bin) add_executable(kleopatra-loader WIN32 himemce.c compat.c diff --git a/loader/himemce.c b/loader/himemce.c index ba388b9..1622ed1 100644 --- a/loader/himemce.c +++ b/loader/himemce.c @@ -63,6 +63,7 @@ main (int argc, char *argv[]) WCHAR *cmdline; BOOL ret; + int result = 0; SetCursor( LoadCursor( NULL, IDC_WAIT ) ); app_name = get_app_name (); @@ -73,12 +74,16 @@ main (int argc, char *argv[]) /* Note that this does not spawn a new process, but just calls into the startup function of the app eventually, and returns with its exit code. */ +#if USE_LOADER + ret = MyCreateProcessW (app_name, cmdline, &result); +#else ret = CreateProcess (app_name, cmdline, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, NULL, NULL); +#endif if (! ret) { ERR ("starting %S failed: %i\n", app_name, GetLastError()); return 1; } - return 0; + return result; } ----------------------------------------------------------------------- Summary of changes: loader/CMakeLists.txt | 5 +++++ loader/himemce.c | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletions(-) hooks/post-receive -- UNNAMED PROJECT http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jan 31 14:04:17 2011 From: cvs at cvs.gnupg.org (by Marcus Brinkmann) Date: Mon, 31 Jan 2011 14:04:17 +0100 Subject: [git] Wincetools - branch, master, updated. dc902c726e960e8c3699228832c774811a8841b6 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "UNNAMED PROJECT". The branch, master has been updated via dc902c726e960e8c3699228832c774811a8841b6 (commit) from 17222082d64b404748f3fdc89bfa297180ed2e74 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit dc902c726e960e8c3699228832c774811a8841b6 Author: Marcus Brinkmann Date: Mon Jan 31 13:43:16 2011 +0100 Show processes, too, and write results to fixed filename on storage card. diff --git a/inspection/virtual-query-imager.py b/inspection/virtual-query-imager.py index 39a12e0..7bbc9c0 100644 --- a/inspection/virtual-query-imager.py +++ b/inspection/virtual-query-imager.py @@ -86,24 +86,44 @@ def drawit (draw, addr, size, state, prot, prot_, type): drawit_ (draw, addr, next, state, prot, prot_, type) addr = next +process = [''] * 32 +threads = [0] * 32 +mode = 0 for line in fileinput.input(): - if line[0] != '0': - continue - # alc-base alc-prot address size state protect type - # 0x00000000 --- --- 0x00001000 0x0000f000 free --- --- unknown - # 0x00010000 --- --- 0x00014000 0x0000a000 reserve --- --- image - # 0x00000000 --- --- 0x0001e000 0x017a2000 free --- --- unknown - # 0x017c0000 --- --- 0x017c0000 0x000fe000 reserve --- --- private - # 0x017c0000 --- --- 0x018be000 0x00002000 commit rw- --- private - # 0x018c0000 --- --- 0x018c0000 0x00002000 commit rw- -n- private - - fields = line.split() - addr, size, state, prot, prot_, type = fields[3:] - addr = int(addr, 16) / 4096 - size = int(size, 16) / 4096 - - drawit (draw, addr, size, state, prot, prot_, type) - + if mode == 0: + field = line.split(); + if field[0] == "alc-base": + mode = 1 + continue + if field[0] == "Process": + continue + # Process PID Base Priority # Threads Base Addr Access Key + # NK.EXE FFFF002 3 2 C2000000 1 + # filesys.exe FFEEE5E 3 18 4000000 2 + # akonadi_agent_server 6CD3C9B6 3 1 6000000 4 + base = int(field[4], 16) + idx = base / (32*1024*1024) - 2; + if idx >= 0 and idx < 32: + process[idx] = field[0] + threads[idx] = int(field[3]) + else: + if line[0] != '0': + continue + # alc-base alc-prot address size state protect type + # 0x00000000 --- --- 0x00001000 0x0000f000 free --- --- unknown + # 0x00010000 --- --- 0x00014000 0x0000a000 reserve --- --- image + # 0x00000000 --- --- 0x0001e000 0x017a2000 free --- --- unknown + # 0x017c0000 --- --- 0x017c0000 0x000fe000 reserve --- --- private + # 0x017c0000 --- --- 0x018be000 0x00002000 commit rw- --- private + # 0x018c0000 --- --- 0x018c0000 0x00002000 commit rw- -n- private + + fields = line.split() + addr, size, state, prot, prot_, type = fields[3:] + addr = int(addr, 16) / 4096 + size = int(size, 16) / 4096 + + drawit (draw, addr, size, state, prot, prot_, type) + # Create grid. for col in xrange(slots): @@ -163,6 +183,11 @@ writerow (0, "Slot 0: Active Process") writerow (1, "Slot 1: ROM Image") for i in xrange (31): writerow (2 + i, "Slot %2i: Process %i" % (i + 2, i)) + if process[i] != "": + if threads[i] > 1: + writerow (2 + i, " %s (%i threads)" % (process[i], threads[i])) + else: + writerow (2 + i, " %s" % (process[i])) for i in xrange (26): writerow (33 + i, "Slot %2i: Shared Area" % (33 + i)) writerow (59, "Slot 59: Driver Stacks") diff --git a/inspection/virtual-query.c b/inspection/virtual-query.c index f47ddf5..d97075c 100644 --- a/inspection/virtual-query.c +++ b/inspection/virtual-query.c @@ -1,10 +1,12 @@ #include #include +FILE *fp; + void dump_mbi_header () { - printf ("alc-base alc-prot address size state protect type \n"); + fprintf (fp, "alc-base alc-prot address size state protect type \n"); } @@ -20,7 +22,7 @@ dump_protect_flags (DWORD flags) DWORD px = flags & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY); - printf ("%c%c%c %c%c%c ", + fprintf (fp, "%c%c%c %c%c%c ", pr ? 'r' : '-', pc ? 'c' : (pw ? 'w' : '-'), px ? 'x' : '-', (flags & PAGE_GUARD) ? 'g' : '-', (flags & PAGE_NOCACHE) ? 'n' : '-', @@ -37,16 +39,16 @@ dump_state (DWORD state) switch (state) { case MEM_COMMIT: - printf ("commit "); + fprintf (fp, "commit "); return; case MEM_FREE: - printf ("free "); + fprintf (fp, "free "); return; case MEM_RESERVE: - printf ("reserve "); + fprintf (fp, "reserve "); return; default: - printf ("unknown "); + fprintf (fp, "unknown "); } } @@ -57,16 +59,16 @@ dump_type (DWORD mtype) switch (mtype) { case MEM_IMAGE: - printf ("image "); + fprintf (fp, "image "); return; case MEM_MAPPED: - printf ("mapped "); + fprintf (fp, "mapped "); return; case MEM_PRIVATE: - printf ("private "); + fprintf (fp, "private "); return; default: - printf ("unknown "); + fprintf (fp, "unknown "); } } @@ -74,16 +76,76 @@ dump_type (DWORD mtype) void dump_mbi (PMEMORY_BASIC_INFORMATION mbi) { - printf ("0x%08x ", mbi->AllocationBase); + fprintf (fp, "0x%08x ", mbi->AllocationBase); dump_protect_flags (mbi->AllocationProtect); - printf ("0x%08x ", mbi->BaseAddress); - printf ("0x%08x ", mbi->RegionSize); + fprintf (fp, "0x%08x ", mbi->BaseAddress); + fprintf (fp, "0x%08x ", mbi->RegionSize); dump_state (mbi->State); dump_protect_flags (mbi->Protect); dump_type (mbi->Type); - printf ("\n"); + fprintf (fp, "\n"); } +#include +#include +#define MAX_PROCESSES 32 + +DWORD GetMaxProcessNameLength( PROCESSENTRY32 lppe[MAX_PROCESSES], DWORD ProcessCount ) +{ + DWORD index ; + DWORD MaxLength = 0; + DWORD CurrentLength; + for( index = 0; index < ProcessCount; index++ ) + { + CurrentLength = wcslen( lppe[ index ].szExeFile ); + if( MaxLength < CurrentLength ) + MaxLength = CurrentLength; + } + return MaxLength; +} + +#define TH32CS_SNAPNOHEAPS 0x40000000 + +DWORD GetRunningProcesses( PROCESSENTRY32 *pProcess ) +{ + HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS|TH32CS_SNAPNOHEAPS, 0); + DWORD index = 0; + if(hSnapShot == (HANDLE)-1) + { +#if 1 + fprintf (fp, "GetRunningProcesses: Failed CreateToolhelp32Snapshot Error: %d\n", + GetLastError()); +#endif + return 0; + } + + memset(pProcess,0,sizeof(PROCESSENTRY32)); + index = 0; + pProcess->dwSize = sizeof(PROCESSENTRY32); + if(Process32First(hSnapShot, pProcess)) + { + while(TRUE) + { + index += 1; + if( index < MAX_PROCESSES ) + { + memcpy( pProcess + 1, pProcess, sizeof(PROCESSENTRY32)); + pProcess++; + if(!Process32Next(hSnapShot, pProcess)) + { + break; + } + } + else + { + index = MAX_PROCESSES; + break; + } + } + } + CloseToolhelp32Snapshot (hSnapShot); + return index ; +} int main (int argc, char* argv[]) @@ -93,6 +155,37 @@ main (int argc, char* argv[]) void *addr; int skipping = 0; + fp = fopen ("\\Speicherkarte\\vmemory.txt", "w"); + { + PROCESSENTRY32 *CurrentProcess; + PROCESSENTRY32 Process[ MAX_PROCESSES ]; + DWORD ProcessCount; + DWORD index ; + DWORD MaxProcessNameLength; + // Get the list of running processes + ProcessCount = GetRunningProcesses( Process ); + // Get the length of the longest process name so that we can format + // the output to be pretty + MaxProcessNameLength = GetMaxProcessNameLength( Process, ProcessCount ); + // Output a header to describe each column + fprintf (fp, "%-*s %8s %13s %9s %9s %10s\n", + MaxProcessNameLength, "Process", "PID", "Base Priority", "# Threads", "Base Addr", "Access Key"); + + // Output information for each running process + for( index = 0; index < ProcessCount; index++ ) + { + CurrentProcess = &(Process[ index ] ); + fprintf (fp, "%-*S %8X %13d %9d %9X %10X\n", + MaxProcessNameLength, CurrentProcess->szExeFile, + CurrentProcess->th32ProcessID, + CurrentProcess->pcPriClassBase, + CurrentProcess->cntThreads, + CurrentProcess->th32MemoryBase, + CurrentProcess->th32AccessKey + ); + } + } + memset (&si, '\0', sizeof (si)); GetSystemInfo (&si); dump_mbi_header (); @@ -108,7 +201,7 @@ main (int argc, char* argv[]) if (res == 0) { if (!skipping) - printf ("Skipping over %p...\n", addr); + fprintf (fp, "Skipping over %p...\n", addr); skipping = 1; new_addr = addr + si.dwPageSize; if (new_addr < addr) @@ -118,7 +211,7 @@ main (int argc, char* argv[]) } if (res != sizeof (mbi)) { - printf ("Unexpected return size: %i (expected %i)\n", + fprintf (fp, "Unexpected return size: %i (expected %i)\n", res, sizeof (mbi)); } skipping = 0; @@ -132,7 +225,8 @@ main (int argc, char* argv[]) while (1); /* Give ssh time to flush buffers. */ - fflush (stdout); + fflush (fp); + fclose (fp); Sleep (300); return 0; } ----------------------------------------------------------------------- Summary of changes: inspection/virtual-query-imager.py | 59 ++++++++++++----- inspection/virtual-query.c | 128 +++++++++++++++++++++++++++++++----- 2 files changed, 153 insertions(+), 34 deletions(-) hooks/post-receive -- UNNAMED PROJECT http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jan 31 14:33:48 2011 From: cvs at cvs.gnupg.org (by Marcus Brinkmann) Date: Mon, 31 Jan 2011 14:33:48 +0100 Subject: [git] Wincetools - branch, master, updated. 528dacbcc3f3faa326507ecdd5d2a9b39125fd6f Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "UNNAMED PROJECT". The branch, master has been updated via 528dacbcc3f3faa326507ecdd5d2a9b39125fd6f (commit) from dc902c726e960e8c3699228832c774811a8841b6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 528dacbcc3f3faa326507ecdd5d2a9b39125fd6f Author: Marcus Brinkmann Date: Mon Jan 31 14:13:03 2011 +0100 Remove void pointer arithmetic. diff --git a/inspection/virtual-query.c b/inspection/virtual-query.c index d97075c..6db3795 100644 --- a/inspection/virtual-query.c +++ b/inspection/virtual-query.c @@ -203,7 +203,7 @@ main (int argc, char* argv[]) if (!skipping) fprintf (fp, "Skipping over %p...\n", addr); skipping = 1; - new_addr = addr + si.dwPageSize; + new_addr = (void*)(((unsigned int)addr) + si.dwPageSize); if (new_addr < addr) break; addr = new_addr; @@ -217,7 +217,7 @@ main (int argc, char* argv[]) skipping = 0; dump_mbi (&mbi); /* Check for overflow. */ - new_addr = addr + mbi.RegionSize; + new_addr = (void*)(((unsigned int)addr) + mbi.RegionSize); if (new_addr < addr) break; addr = new_addr; ----------------------------------------------------------------------- Summary of changes: inspection/virtual-query.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- UNNAMED PROJECT http://git.gnupg.org From cvs at cvs.gnupg.org Mon Jan 31 16:02:43 2011 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 31 Jan 2011 16:02:43 +0100 Subject: [git] GCRYPT - branch, ECC-INTEGRATION-1-5, updated. libgcrypt-1.4.4-61-g7cb0d35 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, ECC-INTEGRATION-1-5 has been updated via 7cb0d357f1564b2ba3fdde707bd9ee7272059d5b (commit) via 0b1d70dcd6b81b1bc10f574e1b34ac7723e245a2 (commit) via 1517b088d3b0602990dba0002ea16221387ad30f (commit) via 55563efccdafc8fb470cab0cae6d186147cc09b6 (commit) via f4786ac5fe01ba111eee27d1a1e9f3d40a9fac02 (commit) via 2089236f5713118e8adbaf8482730e3f2c556c1a (commit) via 3bbd874e677c5330b93591c3ae38f9e9372ebcd5 (commit) from def2727f8bee594b2b51863391296468813c604b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 7cb0d357f1564b2ba3fdde707bd9ee7272059d5b Author: Werner Koch Date: Mon Jan 31 15:35:08 2011 +0100 Changed ecdh parameter names and fixed MPI allocation. diff --git a/NEWS b/NEWS index 0724009..48b2e06 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,8 @@ Noteworthy changes in version 1.5.x (unreleased) * Support ECDH. + * gcry_sexp_build does now support opaque MPIs with "%m". + * Interface changes relative to the 1.4.2 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GCRY_CIPHER_MODE_AESWRAP NEW. diff --git a/cipher/ChangeLog b/cipher/ChangeLog index 36773ab..0f33f7a 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,10 @@ +2011-01-31 Werner Koch + + * ecc.c (ecc_encrypt_raw, ecc_decrypt_raw): Do not free passed + parameters. + (ecc_sk_free, ecc_pk_free): Remove. + (test_keys): Replace ecc_pk_free by point_free and curve_free. + 2011-01-28 Werner Koch * pubkey.c (gcry_pk_genkey): Hack to insert the used curve name. diff --git a/cipher/ecc.c b/cipher/ecc.c index 4561749..8b60895 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -351,29 +351,6 @@ curve_free (elliptic_curve_t *E) /* - * Release a PK object. - */ -static void -ecc_pk_free (ECC_public_key *pk) -{ - point_free (&pk->Q); - curve_free (&pk->E); -} - - -/* - * Release a SK object. - */ -static void -ecc_sk_free (ECC_secret_key *sk) -{ - point_free (&sk->Q); - curve_free (&sk->E); - mpi_free (sk->d); sk->d = NULL; -} - - -/* * Return a copy of a curve object. */ static elliptic_curve_t @@ -447,7 +424,8 @@ gen_k (gcry_mpi_t p, int security_level) nbits = mpi_get_nbits (p); k = mpi_snew (nbits); if (DBG_CIPHER) - log_debug ("choosing a random k of %u bits\n", nbits); + log_debug ("choosing a random k of %u bits at seclevel %d\n", + nbits, security_level); gcry_mpi_randomize (k, nbits, security_level); @@ -562,9 +540,6 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, } random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; - if (DBG_CIPHER) - log_debug ("choosing a random x of size %u%s\n", nbits, - transient_key? " (transient-key)":""); d = gen_k (E.n, random_level); /* Compute Q. */ @@ -648,7 +623,8 @@ test_keys (ECC_secret_key *sk, unsigned int nbits) if (DBG_CIPHER) log_debug ("ECDSA operation: sign, verify ok.\n"); - ecc_pk_free (&pk); + point_free (&pk.Q); + curve_free (&pk.E); point_free (&R_); mpi_free (s); @@ -1368,7 +1344,8 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k, } _gcry_mpi_ec_free (ctx); - ecc_pk_free (&pk); + point_free (&pk.E.G); + point_free (&pk.Q); if (!result[0] || !result[1]) { @@ -1469,7 +1446,9 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, point_free (&R); _gcry_mpi_ec_free (ctx); - ecc_sk_free (&sk) ; + point_free (&kG); + point_free (&sk.E.G); + point_free (&sk.Q); if (!r) return GPG_ERR_ENOMEM; @@ -1678,7 +1657,7 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = gcry_pk_spec_t _gcry_pubkey_spec_ecdh = { "ECDH", ecdh_names, - "pabgnq", "pabgnqd", "rs", "", "pabgnq", + "pabgnq", "pabgnqd", "se", "", "pabgnq", GCRY_PK_USAGE_ENCR, ecc_generate, ecc_check_secret_key, diff --git a/cipher/pubkey.c b/cipher/pubkey.c index d540866..b2de4e6 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -2274,7 +2274,6 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) while (nelem < DIM (mpis)) mpis[nelem++] = NULL; - log_debug ("-->%s<-- %d\n", string, percent_s_idx); { int elem_n = strlen (pub_elems) + strlen (sec_elems); void **arg_list; diff --git a/src/ChangeLog b/src/ChangeLog index fe267b0..f2fbb32 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +2011-01-31 Werner Koch + + * sexp.c (vsexp_sscan): Allow opaque MPIs in "%m". + 2010-08-27 Werner Koch * g10lib.h (HWF_INTEL_AES): New. diff --git a/src/sexp.c b/src/sexp.c index d4f238b..a64ad42 100644 --- a/src/sexp.c +++ b/src/sexp.c @@ -1257,36 +1257,76 @@ vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff, ARG_NEXT (m, gcry_mpi_t); - if (gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &nm, m)) - BUG (); + if (gcry_mpi_get_flag (m, GCRYMPI_FLAG_OPAQUE)) + { + void *mp; + unsigned int nbits; - MAKE_SPACE (nm); - if (!gcry_is_secure (c.sexp->d) - && gcry_mpi_get_flag ( m, GCRYMPI_FLAG_SECURE)) - { - /* We have to switch to secure allocation. */ - gcry_sexp_t newsexp; - byte *newhead; + mp = gcry_mpi_get_opaque (m, &nbits); + nm = (nbits+7)/8; + if (mp && nm) + { + MAKE_SPACE (nm); + if (!gcry_is_secure (c.sexp->d) + && gcry_mpi_get_flag (m, GCRYMPI_FLAG_SECURE)) + { + /* We have to switch to secure allocation. */ + gcry_sexp_t newsexp; + byte *newhead; + + newsexp = gcry_malloc_secure (sizeof *newsexp + + c.allocated - 1); + if (!newsexp) + { + err = gpg_err_code_from_errno (errno); + goto leave; + } + newhead = newsexp->d; + memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d)); + c.pos = newhead + (c.pos - c.sexp->d); + gcry_free (c.sexp); + c.sexp = newsexp; + } + + *c.pos++ = ST_DATA; + STORE_LEN (c.pos, nm); + memcpy (c.pos, mp, nm); + c.pos += nm; + } + } + else + { + if (gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &nm, m)) + BUG (); - newsexp = gcry_malloc_secure (sizeof *newsexp - + c.allocated - 1); - if (!newsexp) + MAKE_SPACE (nm); + if (!gcry_is_secure (c.sexp->d) + && gcry_mpi_get_flag ( m, GCRYMPI_FLAG_SECURE)) { - err = gpg_err_code_from_errno (errno); - goto leave; + /* We have to switch to secure allocation. */ + gcry_sexp_t newsexp; + byte *newhead; + + newsexp = gcry_malloc_secure (sizeof *newsexp + + c.allocated - 1); + if (!newsexp) + { + err = gpg_err_code_from_errno (errno); + goto leave; + } + newhead = newsexp->d; + memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d)); + c.pos = newhead + (c.pos - c.sexp->d); + gcry_free (c.sexp); + c.sexp = newsexp; } - newhead = newsexp->d; - memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d)); - c.pos = newhead + (c.pos - c.sexp->d); - gcry_free (c.sexp); - c.sexp = newsexp; - } - *c.pos++ = ST_DATA; - STORE_LEN (c.pos, nm); - if (gcry_mpi_print (GCRYMPI_FMT_STD, c.pos, nm, &nm, m)) - BUG (); - c.pos += nm; + *c.pos++ = ST_DATA; + STORE_LEN (c.pos, nm); + if (gcry_mpi_print (GCRYMPI_FMT_STD, c.pos, nm, &nm, m)) + BUG (); + c.pos += nm; + } } else if (*p == 's') { commit 0b1d70dcd6b81b1bc10f574e1b34ac7723e245a2 Author: Werner Koch Date: Mon Jan 31 09:29:20 2011 +0100 Return used curve name with ECC key generation diff --git a/cipher/ChangeLog b/cipher/ChangeLog index 64ddb13..36773ab 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,7 @@ +2011-01-28 Werner Koch + + * pubkey.c (gcry_pk_genkey): Hack to insert the used curve name. + 2011-01-27 Werner Koch * ecc.c (fill_in_curve): Remove. @@ -22,6 +26,10 @@ readability. Use ECC_public_key instead of ECC_secret_key. Require a caller to pass a complete pkey array. (ecc_decrypt_raw): Require a caller to pass a complete skey array. + (elliptic_curve_t): Add field NAME. + (fill_in_curve): Set field. + (generate_key): Add arg R_USED_CURVE. + (ecc_generate_ext): Return used curve name. 2011-01-26 Werner Koch diff --git a/cipher/ecc.c b/cipher/ecc.c index ae55f8c..4561749 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -68,6 +68,7 @@ typedef struct gcry_mpi_t b; /* Second coefficient of the Weierstrass equation. */ mpi_point_t G; /* Base point (generator). */ gcry_mpi_t n; /* Order of G. */ + const char *name; /* Name of curve or NULL. */ } elliptic_curve_t; @@ -465,13 +466,17 @@ fill_in_curve (unsigned int nbits, const char *name, elliptic_curve_t *curve, unsigned int *r_nbits) { int idx, aliasno; + const char *resname = NULL; /* Set to a found curve name. */ if (name) { - /* First check nor native curves. */ + /* First check our native curves. */ for (idx = 0; domain_parms[idx].desc; idx++) if (!strcmp (name, domain_parms[idx].desc)) - break; + { + resname = domain_parms[idx].desc; + break; + } /* If not found consult the alias table. */ if (!domain_parms[idx].desc) { @@ -483,7 +488,10 @@ fill_in_curve (unsigned int nbits, const char *name, for (idx = 0; domain_parms[idx].desc; idx++) if (!strcmp (curve_aliases[aliasno].name, domain_parms[idx].desc)) - break; + { + resname = domain_parms[idx].desc; + break; + } } } } @@ -510,6 +518,7 @@ fill_in_curve (unsigned int nbits, const char *name, curve->G.x = scanval (domain_parms[idx].g_x); curve->G.y = scanval (domain_parms[idx].g_y); curve->G.z = mpi_alloc_set_ui (1); + curve->name = resname; return 0; } @@ -523,7 +532,8 @@ static gpg_err_code_t generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, int transient_key, gcry_mpi_t g_x, gcry_mpi_t g_y, - gcry_mpi_t q_x, gcry_mpi_t q_y) + gcry_mpi_t q_x, gcry_mpi_t q_y, + const char **r_usedcurve) { gpg_err_code_t err; elliptic_curve_t E; @@ -532,6 +542,8 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, mpi_ec_t ctx; gcry_random_level_t random_level; + *r_usedcurve = NULL; + err = fill_in_curve (nbits, name, &E, &nbits); if (err) return err; @@ -544,7 +556,9 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, log_mpidump ("ecgen curve n", E.n); log_mpidump ("ecgen curve Gx", E.G.x); log_mpidump ("ecgen curve Gy", E.G.y); - log_mpidump ("ecgen cyrve Gz", E.G.z); + log_mpidump ("ecgen curve Gz", E.G.z); + if (E.name) + log_debug ("ecgen curve used: %s\n", E.name); } random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; @@ -584,6 +598,8 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, point_free (&Q); mpi_free (d); + + *r_usedcurve = E.name; curve_free (&E); /* Now we can test our keys (this should never fail!). */ @@ -992,10 +1008,10 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, char *curve_name = NULL; gcry_sexp_t l1; int transient_key = 0; + const char *usedcurve = NULL; (void)algo; (void)evalue; - (void)r_extrainfo; if (genparms) { @@ -1026,10 +1042,13 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, g_y = mpi_new (0); q_x = mpi_new (0); q_y = mpi_new (0); - ec = generate_key (&sk, nbits, curve_name, transient_key, g_x, g_y, q_x, q_y); + ec = generate_key (&sk, nbits, curve_name, transient_key, g_x, g_y, q_x, q_y, + &usedcurve); gcry_free (curve_name); if (ec) return ec; + if (usedcurve) /* Fixme: No error return checking. */ + gcry_sexp_build (r_extrainfo, NULL, "(curve %s)", usedcurve); skey[0] = sk.E.p; skey[1] = sk.E.a; @@ -1050,7 +1069,7 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, /* Make an empty list of factors. */ *retfactors = gcry_calloc ( 1, sizeof **retfactors ); if (!*retfactors) - return gpg_err_code_from_syserror (); + return gpg_err_code_from_syserror (); /* Fixme: relase mem? */ if (DBG_CIPHER) { @@ -1659,7 +1678,7 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = gcry_pk_spec_t _gcry_pubkey_spec_ecdh = { "ECDH", ecdh_names, - "pabgnq", "pabgnqd", "", "rs", "pabgnq", + "pabgnq", "pabgnqd", "rs", "", "pabgnq", GCRY_PK_USAGE_ENCR, ecc_generate, ecc_check_secret_key, diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 2861d29..d540866 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -2078,7 +2078,7 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) char *name = NULL; size_t n; gcry_err_code_t rc = GPG_ERR_NO_ERROR; - int i; + int i, j; const char *algo_name = NULL; int algo; const char *sec_elems = NULL, *pub_elems = NULL; @@ -2196,6 +2196,7 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) char *string, *p; size_t nelem=0, nelem_cp = 0, needed=0; gcry_mpi_t mpis[30]; + int percent_s_idx = -1; /* Estimate size of format string. */ nelem = strlen (pub_elems) + strlen (sec_elems); @@ -2230,6 +2231,13 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) p = stpcpy (p, "%m)"); mpis[nelem++] = skey[i]; } + if (extrainfo && (algo == GCRY_PK_ECDSA || algo == GCRY_PK_ECDH)) + { + /* Very ugly hack to insert the used curve parameter into the + list of public key parameters. */ + percent_s_idx = nelem; + p = stpcpy (p, "%S"); + } p = stpcpy (p, "))"); p = stpcpy (p, "(private-key("); p = stpcpy (p, algo_name); @@ -2245,7 +2253,7 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) /* Hack to make release_mpi_array() work. */ skey[i] = NULL; - if (extrainfo) + if (extrainfo && percent_s_idx == -1) { /* If we have extrainfo we should not have any factors. */ p = stpcpy (p, "%S"); @@ -2266,6 +2274,7 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) while (nelem < DIM (mpis)) mpis[nelem++] = NULL; + log_debug ("-->%s<-- %d\n", string, percent_s_idx); { int elem_n = strlen (pub_elems) + strlen (sec_elems); void **arg_list; @@ -2277,16 +2286,19 @@ gcry_pk_genkey (gcry_sexp_t *r_key, gcry_sexp_t s_parms) rc = gpg_err_code_from_errno (errno); goto leave; } - for (i = 0; i < elem_n; i++) - arg_list[i] = mpis + i; - if (extrainfo) - arg_list[i] = &extrainfo; + for (i = j = 0; i < elem_n; i++) + { + if (i == percent_s_idx) + arg_list[j++] = &extrainfo; + arg_list[j++] = mpis + i; + } + if (extrainfo && percent_s_idx == -1) + arg_list[j] = &extrainfo; else if (factors && factors[0]) { for (; i < nelem_cp; i++) - arg_list[i] = factors + i - elem_n; + arg_list[j++] = factors + i - elem_n; } - rc = gcry_sexp_build_array (r_key, NULL, string, arg_list); gcry_free (arg_list); if (rc) commit 1517b088d3b0602990dba0002ea16221387ad30f Author: Werner Koch Date: Thu Jan 27 11:32:58 2011 +0100 Reverted the API to the old one. Storing thy curve name into an MPI and dropping all the other parameters breaks the ABI. Further it as not anymore possible to specify arbitrary curves. Thus I had to revert it to the old ABI. Another advantage is that the required ECDH changes are now minimal. The disadvantage is that we need to adjust the GnuPG code and do the curve selection and translation to DER encoded OIDs itself. diff --git a/cipher/ChangeLog b/cipher/ChangeLog index f38c818..64ddb13 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,28 @@ +2011-01-27 Werner Koch + + * ecc.c (fill_in_curve): Remove. + (MAX_ECC_OID_LEN): Remove. + (elliptic_curve_t, ecc_domain_parms_t): Remove field NAME_OID. + (curve_oid_NISTP256, curve_oid_NISTP384, curve_oid_NISTP521): + Remove. + (generate_curve): Rename to .. + (fill_in_curve): this. Remove setting of NAME_OID. + (ecc_generate_ext): Remove kek-params code. + (generate_key): Remove name oid stuff. + (name_oid_to_mpi): Remove. + (mpi_to_name_oid): Remove. + (ecc_generate_ext): Revert to pre-ECDH integration state. + (ecc_check_secret_key): Ditto. + (ecc_sign): Ditto. + (ecc_verify): Ditto. + (ecc_get_nbits): Revert. + (_gcry_pubkey_spec_ecdsa): Revert list or parameters. + (_gcry_pubkey_spec_ecdh): Use same parameter list as for ECDSA. + (ecc_encrypt_raw): Change name of arg DATA to K for better + readability. Use ECC_public_key instead of ECC_secret_key. + Require a caller to pass a complete pkey array. + (ecc_decrypt_raw): Require a caller to pass a complete skey array. + 2011-01-26 Werner Koch * pubkey.c (sexp_to_key): Revert to pre-ECDH integration state. diff --git a/cipher/ecc.c b/cipher/ecc.c index 9ec4bb6..ae55f8c 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -33,20 +33,21 @@ up. In fact there is not much left of the orginally code except for some variable names and the text book implementaion of the sign and verification algorithms. The arithmetic functions have entirely - been rewritten and moved to mpi/ec.c. */ + been rewritten and moved to mpi/ec.c. + + ECDH encrypt and decrypt code written by Andrey Jivsov, +*/ /* TODO: - - If we support point compression we need to decide how to compute - the keygrip - it should not change due to compression. + - If we support point compression we need to uncompress before + computing the keygrip - In mpi/ec.c we use mpi_powm for x^2 mod p: Either implement a special case in mpi_powm or check whether mpi_mulm is faster. - Decide whether we should hide the mpi_point_t definition. - - - Support more than just ECDSA. */ @@ -58,10 +59,6 @@ #include "g10lib.h" #include "mpi.h" #include "cipher.h" -#include - -/* The maximum length of our DER encoded OID. */ -#define MAX_ECC_OID_LEN 16 /* Definition of a curve. */ typedef struct @@ -71,10 +68,6 @@ typedef struct gcry_mpi_t b; /* Second coefficient of the Weierstrass equation. */ mpi_point_t G; /* Base point (generator). */ gcry_mpi_t n; /* Order of G. */ - - /* One byte length, followed by DER representation of curve OID: - * N byte OID is encoded as N+1 bytes as follows: N x0 x1 ... xN. */ - byte name_oid[MAX_ECC_OID_LEN]; } elliptic_curve_t; @@ -127,18 +120,10 @@ static const struct { NULL, NULL} }; -static const byte curve_oid_NISTP256[] = - { 8, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07 }; -static const byte curve_oid_NISTP384[] = - { 5, 0x2B, 0x81, 0x04, 0x00, 0x22 }; -static const byte curve_oid_NISTP521[] = - { 5, 0x2B, 0x81, 0x04, 0x00, 0x23 }; - typedef struct { const char *desc; /* Description of the curve. */ unsigned int nbits; /* Number of bits. */ unsigned int fips:1; /* True if this is a FIPS140-2 approved curve. */ - const byte *name_oid; /* points to LEN + curve DER OID, optional */ const char *p; /* Order of the prime field. */ const char *a, *b; /* The coefficients. */ const char *n; /* The order of the base point. */ @@ -149,7 +134,7 @@ typedef struct { static const ecc_domain_parms_t domain_parms[] = { { - "NIST P-192", 192, 1, NULL, + "NIST P-192", 192, 1, "0xfffffffffffffffffffffffffffffffeffffffffffffffff", "0xfffffffffffffffffffffffffffffffefffffffffffffffc", "0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", @@ -159,7 +144,7 @@ static const ecc_domain_parms_t domain_parms[] = "0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811" }, { - "NIST P-224", 224, 1, NULL, + "NIST P-224", 224, 1, "0xffffffffffffffffffffffffffffffff000000000000000000000001", "0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe", "0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4", @@ -169,7 +154,7 @@ static const ecc_domain_parms_t domain_parms[] = "0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34" }, { - "NIST P-256", 256, 1, curve_oid_NISTP256, + "NIST P-256", 256, 1, "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff", "0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc", "0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", @@ -179,7 +164,7 @@ static const ecc_domain_parms_t domain_parms[] = "0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5" }, { - "NIST P-384", 384, 1, curve_oid_NISTP384, + "NIST P-384", 384, 1, "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" "ffffffff0000000000000000ffffffff", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" @@ -195,7 +180,7 @@ static const ecc_domain_parms_t domain_parms[] = "0a60b1ce1d7e819d7a431d7c90ea0e5f" }, { - "NIST P-521", 521, 1, curve_oid_NISTP521, + "NIST P-521", 521, 1, "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" @@ -211,7 +196,7 @@ static const ecc_domain_parms_t domain_parms[] = "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650" }, - { "brainpoolP160r1", 160, 0, NULL, + { "brainpoolP160r1", 160, 0, "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f", "0x340e7be2a280eb74e2be61bada745d97e8f7c300", "0x1e589a8595423412134faa2dbdec95c8d8675e58", @@ -220,7 +205,7 @@ static const ecc_domain_parms_t domain_parms[] = "0x1667cb477a1a8ec338f94741669c976316da6321" }, - { "brainpoolP192r1", 192, 0, NULL, + { "brainpoolP192r1", 192, 0, "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297", "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef", "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9", @@ -229,7 +214,7 @@ static const ecc_domain_parms_t domain_parms[] = "0x14b690866abd5bb88b5f4828c1490002e6773fa2fa299b8f" }, - { "brainpoolP224r1", 224, 0, NULL, + { "brainpoolP224r1", 224, 0, "0xd7c134aa264366862a18302575d1d787b09f075797da89f57ec8c0ff", "0x68a5e62ca9ce6c1c299803a6c1530b514e182ad8b0042a59cad29f43", "0x2580f63ccfe44138870713b1a92369e33e2135d266dbb372386c400b", @@ -238,7 +223,7 @@ static const ecc_domain_parms_t domain_parms[] = "0x58aa56f772c0726f24c6b89e4ecdac24354b9e99caa3f6d3761402cd" }, - { "brainpoolP256r1", 256, 0, NULL, + { "brainpoolP256r1", 256, 0, "0xa9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e5377", "0x7d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9", "0x26dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b6", @@ -247,7 +232,7 @@ static const ecc_domain_parms_t domain_parms[] = "0x547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f046997" }, - { "brainpoolP320r1", 320, 0, NULL, + { "brainpoolP320r1", 320, 0, "0xd35e472036bc4fb7e13c785ed201e065f98fcfa6f6f40def4f92b9ec7893ec28" "fcd412b1f1b32e27", "0x3ee30b568fbab0f883ccebd46d3f3bb8a2a73513f5eb79da66190eb085ffa9f4" @@ -262,7 +247,7 @@ static const ecc_domain_parms_t domain_parms[] = "d35245d1692e8ee1" }, - { "brainpoolP384r1", 384, 0, NULL, + { "brainpoolP384r1", 384, 0, "0x8cb91e82a3386d280f5d6f7e50e641df152f7109ed5456b412b1da197fb71123" "acd3a729901d1a71874700133107ec53", "0x7bc382c63d8c150c3c72080ace05afa0c2bea28e4fb22787139165efba91f90f" @@ -277,7 +262,7 @@ static const ecc_domain_parms_t domain_parms[] = "0e4646217791811142820341263c5315" }, - { "brainpoolP512r1", 512, 0, NULL, + { "brainpoolP512r1", 512, 0, "0xaadd9db8dbe9c48b3fd4e6ae33c9fc07cb308db3b3c9d20ed6639cca70330871" "7d4d9b009bc66842aecda12ae6a380e62881ff2f2d82c68528aa6056583a48f3", "0x7830a3318b603b89e2327145ac234cc594cbdd8d3df91610a83441caea9863bc" @@ -292,7 +277,7 @@ static const ecc_domain_parms_t domain_parms[] = "b2dcde494a5f485e5bca4bd88a2763aed1ca2b2fa8f0540678cd1e0f3ad80892" }, - { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL } + { NULL, 0, 0, NULL, NULL, NULL, NULL } }; @@ -471,12 +456,13 @@ gen_k (gcry_mpi_t p, int security_level) } -/* Generate the crypto system setup. As of now the fix NIST - recommended values are used. The subgroup generator point is in - another function: gen_big_point. */ +/* Generate the crypto system setup. This function takes the NAME of + a curve or the desired number of bits and stores at R_CURVE the + parameters of the named curve or those of a suitable curve. The + chosen number of bits is stored on R_NBITS. */ static gpg_err_code_t -generate_curve (unsigned int nbits, const char *name, - elliptic_curve_t *curve, unsigned int *r_nbits) +fill_in_curve (unsigned int nbits, const char *name, + elliptic_curve_t *curve, unsigned int *r_nbits) { int idx, aliasno; @@ -516,7 +502,6 @@ generate_curve (unsigned int nbits, const char *name, if (fips_mode () && !domain_parms[idx].fips ) return GPG_ERR_NOT_SUPPORTED; - *r_nbits = domain_parms[idx].nbits; curve->p = scanval (domain_parms[idx].p); curve->a = scanval (domain_parms[idx].a); @@ -525,10 +510,6 @@ generate_curve (unsigned int nbits, const char *name, curve->G.x = scanval (domain_parms[idx].g_x); curve->G.y = scanval (domain_parms[idx].g_y); curve->G.z = mpi_alloc_set_ui (1); - memset (curve->name_oid, 0, sizeof(curve->name_oid)); - if (domain_parms[idx].name_oid) - memcpy (curve->name_oid, - domain_parms[idx].name_oid, domain_parms[idx].name_oid[0]+1); return 0; } @@ -551,24 +532,19 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, mpi_ec_t ctx; gcry_random_level_t random_level; - err = generate_curve (nbits, name, &E, &nbits); + err = fill_in_curve (nbits, name, &E, &nbits); if (err) return err; if (DBG_CIPHER) { - log_mpidump ("ecgen curve p", E.p); - log_mpidump ("ecgen curve a", E.a); - log_mpidump ("ecgen curve b", E.b); - log_mpidump ("ecgen curve n", E.n); - log_mpidump ("ecgen curve G.x", E.G.x); - /* log_mpidump ("ecc generation Gy", E.G.y); - log_mpidump ("ecc generation Gz", E.G.z); */ - - log_printf ("ecgen curve OID: [%d] ...%02X %02X\n", - E.name_oid[0], - E.name_oid[0]>0 ? E.name_oid[E.name_oid[0]-1] : 0, - E.name_oid[E.name_oid[0]]); + log_mpidump ("ecgen curve p", E.p); + log_mpidump ("ecgen curve a", E.a); + log_mpidump ("ecgen curve b", E.b); + log_mpidump ("ecgen curve n", E.n); + log_mpidump ("ecgen curve Gx", E.G.x); + log_mpidump ("ecgen curve Gy", E.G.y); + log_mpidump ("ecgen cyrve Gz", E.G.z); } random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; @@ -586,7 +562,6 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, sk->E.p = mpi_copy (E.p); sk->E.a = mpi_copy (E.a); sk->E.b = mpi_copy (E.b); - memcpy(sk->E.name_oid, E.name_oid, sizeof(E.name_oid)); point_init (&sk->E.G); point_set (&sk->E.G, &E.G); sk->E.n = mpi_copy (E.n); @@ -611,7 +586,7 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, mpi_free (d); curve_free (&E); - /* Now we can test our keys (this should never fail!). */ + /* Now we can test our keys (this should never fail!). */ test_keys (sk, nbits - 64); return 0; @@ -657,7 +632,7 @@ test_keys (ECC_secret_key *sk, unsigned int nbits) if (DBG_CIPHER) log_debug ("ECDSA operation: sign, verify ok.\n"); - ecc_pk_free( &pk ); + ecc_pk_free (&pk); point_free (&R_); mpi_free (s); @@ -746,9 +721,7 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s) mpi_ec_t ctx; if (DBG_CIPHER) - { log_mpidump ("ecdsa sign hash ", input ); - } k = NULL; dr = mpi_alloc (0); @@ -789,10 +762,10 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s) } if (DBG_CIPHER) - { - log_mpidump ("ecdsa return r ", r ); - log_mpidump ("ecdsa return s ", s ); - } + { + log_mpidump ("ecdsa sign result r ", r); + log_mpidump ("ecdsa sign result s ", s); + } leave: _gcry_mpi_ec_free (ctx); @@ -904,56 +877,7 @@ verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s) } -/* Lookup named curve and fill in internal curve parameters. Returns - GPG_ERR_NOT_FOUND for an unknown OID. */ -static int -fill_in_curve (const byte name_oid[], elliptic_curve_t *curve) -{ - int i; - const ecc_domain_parms_t *p; - - if (!name_oid || !name_oid[0]) - { - log_debug ("ecc OID is malformed\n"); - return GPG_ERR_INV_ARG; - } - - for (i = 0; domain_parms[i].desc; i++) - { - p = domain_parms + i; - if (!p->name_oid || p->name_oid[0] != name_oid[0]) - continue; - if (!memcmp (p->name_oid, name_oid, name_oid[0]+1)) - break; - } - - assert (p); /* FIXME: We need proper error handling. */ - - if (!p->desc) - { - log_debug ("ecc OID is not recognized\n"); - return GPG_ERR_NOT_FOUND; - } - - /* TODO: there is no reason why these values are encoded as ASCII - v.s. binary. [wk] We might want to put the curve defintions into - a table and use a tool to create them. This also solves the - problem of manuallay encoding the OIDs. */ - curve->p = scanval (p->p); - curve->a = scanval (p->a); - curve->b = scanval (p->b); - curve->n = scanval (p->n); - curve->G.x = scanval (p->g_x); - curve->G.y = scanval (p->g_y); - curve->G.z = mpi_alloc_set_ui (1); - - if (DBG_CIPHER) - log_debug ("ec filled in curve %s\n", p->desc); - - return 0; -} - - + /********************************************* ************** interface ****************** *********************************************/ @@ -996,23 +920,6 @@ ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p) } -static gcry_mpi_t -name_oid_to_mpi (const byte *name_oid) -{ - gpg_error_t err; - gcry_mpi_t result; - - if (!name_oid || !name_oid[0]) - return mpi_new (0); - - err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, name_oid, name_oid[0]+1, NULL); - if (err) - log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); - - return result; -} - - /* RESULT must have been initialized and is set on success to the point given by VALUE. */ static gcry_error_t @@ -1072,38 +979,6 @@ os2ec (mpi_point_t *result, gcry_mpi_t value) } -static gcry_err_code_t -mpi_to_name_oid (gcry_mpi_t mpi_in, byte name_oid_out[MAX_ECC_OID_LEN]) -{ - size_t nbytes; - unsigned char *buf; - gcry_error_t err; - - memset (name_oid_out, 0, MAX_ECC_OID_LEN); - - nbytes = (mpi_get_nbits (mpi_in)+7)/8; - if (!nbytes) - return 0; - - buf = gcry_xmalloc (nbytes); - err = gcry_mpi_print (GCRYMPI_FMT_USG, buf, nbytes, &nbytes, mpi_in); - if (err) - { - gcry_free (buf); - return err; - } - if (buf[0]+1 != nbytes || nbytes >= MAX_ECC_OID_LEN) - { - gcry_free (buf); - return GPG_ERR_INV_OBJ; - } - memcpy (name_oid_out, buf, nbytes+1); - gcry_free (buf); - - return 0; -} - - /* Extended version of ecc_generate. */ static gcry_err_code_t ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, @@ -1114,7 +989,6 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, gpg_err_code_t ec; ECC_secret_key sk; gcry_mpi_t g_x, g_y, q_x, q_y; - gcry_mpi_t kek_params = NULL; char *curve_name = NULL; gcry_sexp_t l1; int transient_key = 0; @@ -1142,24 +1016,6 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, transient_key = 1; gcry_sexp_release (l1); } - - /* Parse the "KEK parameters" parameter. */ - l1 = gcry_sexp_find_token (genparms, "kek-params", 0); - if (l1) - { - kek_params = gcry_sexp_nth_mpi (l1, 1, 0); - gcry_sexp_release (l1); - if (!kek_params) - { - log_debug( "ecgen failed to parse 'kek-params'\n" ); - return GPG_ERR_INV_OBJ; /* No value for kek-params. */ - } - if (DBG_CIPHER) - { - log_debug ("ecgen 'kek-params' parameter supplied\n" ); - log_mpidump ("ecgen DH kek-param", kek_params); - } - } } /* NBITS is required if no curve name has been given. */ @@ -1175,25 +1031,19 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, if (ec) return ec; - skey[0] = name_oid_to_mpi( sk.E.name_oid ); /* "c", name OID */ - /* if( (ec=fill_in_curve( sk.E.name_oid, &sk.E )) ) */ - /* return ec; */ - skey[1] = ec2os (q_x, q_y, sk.E.p); /* public key */ - /* "q", public key, the point */ + skey[0] = sk.E.p; + skey[1] = sk.E.a; + skey[2] = sk.E.b; + skey[3] = ec2os (g_x, g_y, sk.E.p); + skey[4] = sk.E.n; + skey[5] = ec2os (q_x, q_y, sk.E.p); + skey[6] = sk.d; + + mpi_free (g_x); + mpi_free (g_y); mpi_free (q_x); mpi_free (q_y); - if (algo == GCRY_PK_ECDSA) - { - skey[2] = sk.d; - } - else - { - /* PARAMS, the last field in the public key portion. */ - skey[2] = (kek_params ? kek_params : mpi_new (0)); - - skey[3] = sk.d; - } point_free (&sk.E.G); point_free (&sk.Q); @@ -1204,19 +1054,13 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, if (DBG_CIPHER) { - if (algo == GCRY_PK_ECDSA) - { - log_mpidump ("ecgen DSA c ", skey[0]); - log_mpidump ("ecgen DSA Q ", skey[1]); - log_mpidump ("ecgen DSA d ", skey[2]); - } - else - { - log_mpidump ("ecgen DH c ", skey[0]); - log_mpidump ("ecgen DH Q ", skey[1]); - log_mpidump ("ecgen DH p ", skey[2]); - log_mpidump ("ecgen DH d ", skey[3]); - } + log_mpidump ("ecgen result p", skey[0]); + log_mpidump ("ecgen result a", skey[1]); + log_mpidump ("ecgen result b", skey[2]); + log_mpidump ("ecgen result G", skey[3]); + log_mpidump ("ecgen result n", skey[4]); + log_mpidump ("ecgen result Q", skey[5]); + log_mpidump ("ecgen result d", skey[6]); } return 0; @@ -1242,7 +1086,7 @@ ecc_get_param (const char *name, gcry_mpi_t *pkey) mpi_ec_t ctx; gcry_mpi_t g_x, g_y; - err = generate_curve (0, name, &E, &nbits); + err = fill_in_curve (0, name, &E, &nbits); if (err) return err; @@ -1261,6 +1105,9 @@ ecc_get_param (const char *name, gcry_mpi_t *pkey) pkey[4] = E.n; pkey[5] = NULL; + mpi_free (g_x); + mpi_free (g_y); + return 0; } @@ -1273,15 +1120,24 @@ ecc_check_secret_key (int algo, gcry_mpi_t *skey) (void)algo; - if (!skey[0] || !skey[1] || !skey[2] ) + /* FIXME: This check looks a bit fishy: Now long is the array? */ + if (!skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] || !skey[5] + || !skey[6]) return GPG_ERR_BAD_MPI; - if( (err=mpi_to_name_oid( skey[0], sk.E.name_oid )) ) - return err; - if( (err=fill_in_curve( sk.E.name_oid, &sk.E )) ) - return err; + sk.E.p = skey[0]; + sk.E.a = skey[1]; + sk.E.b = skey[2]; + point_init (&sk.E.G); + err = os2ec (&sk.E.G, skey[3]); + if (err) + { + point_free (&sk.E.G); + return err; + } + sk.E.n = skey[4]; point_init (&sk.Q); - err = os2ec (&sk.Q, skey[1]); + err = os2ec (&sk.Q, skey[5]); if (err) { point_free (&sk.E.G); @@ -1289,7 +1145,7 @@ ecc_check_secret_key (int algo, gcry_mpi_t *skey) return err; } - sk.d = skey[2]; + sk.d = skey[6]; if (check_secret_key (&sk)) { @@ -1311,22 +1167,30 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey) (void)algo; - if (!data || !skey[0] || !skey[1] || !skey[2] ) + if (!data || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] + || !skey[5] || !skey[6] ) return GPG_ERR_BAD_MPI; - if( (err=mpi_to_name_oid( skey[0], sk.E.name_oid )) ) - return err; - if( (err=fill_in_curve( sk.E.name_oid, &sk.E )) ) - return err; + sk.E.p = skey[0]; + sk.E.a = skey[1]; + sk.E.b = skey[2]; + point_init (&sk.E.G); + err = os2ec (&sk.E.G, skey[3]); + if (err) + { + point_free (&sk.E.G); + return err; + } + sk.E.n = skey[4]; point_init (&sk.Q); - err = os2ec (&sk.Q, skey[1]); + err = os2ec (&sk.Q, skey[5]); if (err) { point_free (&sk.E.G); point_free (&sk.Q); return err; } - sk.d = gcry_mpi_copy( skey[2] ); + sk.d = skey[6]; resarr[0] = mpi_alloc (mpi_get_nlimbs (sk.E.p)); resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.E.p)); @@ -1337,7 +1201,8 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey) mpi_free (resarr[1]); resarr[0] = NULL; /* Mark array as released. */ } - ecc_sk_free( &sk ); + point_free (&sk.E.G); + point_free (&sk.Q); return err; } @@ -1353,35 +1218,40 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, (void)cmp; (void)opaquev; - if (!data[0] || !data[1] || !hash || !pkey[0] || !pkey[1] ) + if (!data[0] || !data[1] || !hash || !pkey[0] || !pkey[1] || !pkey[2] + || !pkey[3] || !pkey[4] || !pkey[5] ) return GPG_ERR_BAD_MPI; - if( (err=mpi_to_name_oid( pkey[0], pk.E.name_oid )) ) - return err; - if( (err=fill_in_curve( pk.E.name_oid, &pk.E )) ) - return err; + pk.E.p = pkey[0]; + pk.E.a = pkey[1]; + pk.E.b = pkey[2]; + point_init (&pk.E.G); + err = os2ec (&pk.E.G, pkey[3]); + if (err) + { + point_free (&pk.E.G); + return err; + } + pk.E.n = pkey[4]; point_init (&pk.Q); - err = os2ec (&pk.Q, pkey[1]); + err = os2ec (&pk.Q, pkey[5]); if (err) { - ecc_pk_free( &pk ); + point_free (&pk.E.G); + point_free (&pk.Q); return err; } err = verify (hash, &pk, data[0], data[1]); - ecc_pk_free( &pk ); + point_free (&pk.E.G); + point_free (&pk.Q); return err; } /* ecdh raw is classic 2-round DH protocol published in 1976. * - * Some overloading is needed to fit it to encrypt/decrypt PK - * interface of libgcrypt. The only need for this complexity is that - * some designs of client of libgcrypt don't allow to get the private - * components of public keys. - * * Overview of ecc_encrypt_raw and ecc_decrypt_raw. * * As with any PK operation, encrypt version uses a public key and @@ -1389,32 +1259,30 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, * * Symbols used below: * G - field generator point - * x - private long-term scalar - * xG - public long-term key + * d - private long-term scalar + * dG - public long-term key * k - ephemeral scalar * kG - ephemeral public key - * xkG - shared secret + * dkG - shared secret * * ecc_encrypt_raw description: * input: * data[0] : private scalar (k) * output: - * resaddr[0] : shared point (k*x*G, where x is the secret scalar of pkey; - * it's the shared secret) - * resaddr[1] : generated ephemeral public key (kG) + * result[0] : shared point (kdG) + * result[1] : generated ephemeral public key (kG) * * ecc_decrypt_raw description: * input: * data[0] : a point kG (ephemeral public key) * output: - * result[0] : shared point (k*x*G, where x is the secret scalar of pkey; - * it's the shared secret) + * result[0] : shared point (kdG) */ static gcry_err_code_t -ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, +ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k, gcry_mpi_t *pkey, int flags) { - ECC_secret_key sk; + ECC_public_key pk; mpi_ec_t ctx; gcry_mpi_t result[2]; int err; @@ -1422,36 +1290,31 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, (void)algo; (void)flags; - if (DBG_CIPHER) - log_debug ("Called ecc_encrypt_raw data size=%d bits, flags=%08x\n", - gcry_mpi_get_nbits (data), flags); - - if ( !data || !pkey[0] || !pkey[1] ) + if (!k + || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4] || !pkey[5]) return GPG_ERR_BAD_MPI; - if (DBG_CIPHER) + pk.E.p = pkey[0]; + pk.E.a = pkey[1]; + pk.E.b = pkey[2]; + point_init (&pk.E.G); + err = os2ec (&pk.E.G, pkey[3]); + if (err) { - log_mpidump ("ecdh encrypt PK c ", pkey[0]); - log_mpidump ("ecdh encrypt PK q ", pkey[1]); - log_mpidump ("ecdh encrypt PK p ", pkey[2]); - log_mpidump ("ecdh encrypt data k", data); + point_free (&pk.E.G); + return err; } - - if ((err=mpi_to_name_oid( pkey[0], sk.E.name_oid ))) - return err; - if ((err=fill_in_curve( sk.E.name_oid, &sk.E ))) - return err; - - point_init (&sk.Q); - err = os2ec (&sk.Q, pkey[1]); - sk.d = gcry_mpi_copy( data ); + pk.E.n = pkey[4]; + point_init (&pk.Q); + err = os2ec (&pk.Q, pkey[5]); if (err) { - ecc_sk_free( &sk ); + point_free (&pk.E.G); + point_free (&pk.Q); return err; } - ctx = _gcry_mpi_ec_init (sk.E.p, sk.E.a); + ctx = _gcry_mpi_ec_init (pk.E.p, pk.E.a); /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */ { @@ -1463,19 +1326,21 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, point_init (&R); - _gcry_mpi_ec_mul_point (&R, sk.d, &sk.Q, ctx); + /* R = kQ <=> R = kdG */ + _gcry_mpi_ec_mul_point (&R, k, &pk.Q, ctx); if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) - log_fatal ("ecdh: Failed to get affine coordinates for xkG\n"); + log_fatal ("ecdh: Failed to get affine coordinates for kdG\n"); - result[0] = ec2os (x, y, sk.E.p); /* xkG */ + result[0] = ec2os (x, y, pk.E.p); - _gcry_mpi_ec_mul_point (&R, sk.d, &sk.E.G, ctx); + /* R = kG */ + _gcry_mpi_ec_mul_point (&R, k, &pk.E.G, ctx); if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) log_fatal ("ecdh: Failed to get affine coordinates for kG\n"); - result[1] = ec2os (x, y, sk.E.p); /* kG */ + result[1] = ec2os (x, y, pk.E.p); mpi_free (x); mpi_free (y); @@ -1484,7 +1349,7 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, } _gcry_mpi_ec_free (ctx); - ecc_sk_free (&sk); + ecc_pk_free (&pk); if (!result[0] || !result[1]) { @@ -1494,10 +1359,6 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, } /* Success. */ - - /* None of 2 returned values are used as is; they are further - * processed at OpenPGP layer. However, they match the number of - * MPIs (2) needed to encrypt a message in OpenPGP format. */ resarr[0] = result[0]; resarr[1] = result[1]; @@ -1507,7 +1368,7 @@ ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, /* input: * data[0] : a point kG (ephemeral public key) * output: - * resaddr[0] : shared point k*x*G + * resaddr[0] : shared point kdG * * see ecc_encrypt_raw for details. */ @@ -1517,6 +1378,7 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, { ECC_secret_key sk; mpi_point_t R; /* Result that we return. */ + mpi_point_t kG; mpi_ec_t ctx; gcry_mpi_t r; int err; @@ -1526,39 +1388,50 @@ ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, *result = NULL; - if (DBG_CIPHER) - log_debug ("Called ecc_encrypt_raw data size=%d bits, flags=%08x\n", - gcry_mpi_get_nbits (data[0]), flags); - - if (!data || !data[0] || !skey[0] || !skey[1] || !skey[3]) + if (!data || !data[0] + || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] + || !skey[5] || !skey[6] ) return GPG_ERR_BAD_MPI; - if (DBG_CIPHER) + point_init (&kG); + err = os2ec (&kG, data[0]); + if (err) { - log_mpidump ("ecdh decrypt SK c ", skey[0]); - log_mpidump ("ecdh decrypt SK q ", skey[1]); - log_mpidump ("ecdh decrypt SK p ", skey[2]); - log_mpidump ("ecdh decrypt data kG", data[0]); + point_free (&kG); + return err; } - if ((err=mpi_to_name_oid( skey[0], sk.E.name_oid ))) - return err; - if ((err=fill_in_curve( sk.E.name_oid, &sk.E ))) - return err; + sk.E.p = skey[0]; + sk.E.a = skey[1]; + sk.E.b = skey[2]; + point_init (&sk.E.G); + err = os2ec (&sk.E.G, skey[3]); + if (err) + { + point_free (&kG); + point_free (&sk.E.G); + return err; + } + sk.E.n = skey[4]; point_init (&sk.Q); - err = os2ec (&sk.Q, data[0]); - sk.d = gcry_mpi_copy (skey[3]); + err = os2ec (&sk.Q, skey[5]); if (err) { - ecc_sk_free (&sk); + point_free (&kG); + point_free (&sk.E.G); + point_free (&sk.Q); return err; } + sk.d = skey[6]; ctx = _gcry_mpi_ec_init (sk.E.p, sk.E.a); + /* R = dkG */ point_init (&R); - _gcry_mpi_ec_mul_point (&R, sk.d, &sk.Q, ctx); + _gcry_mpi_ec_mul_point (&R, sk.d, &kG, ctx); + + point_free (&kG); /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so: */ { @@ -1594,8 +1467,8 @@ static unsigned int ecc_get_nbits (int algo, gcry_mpi_t *pkey) { (void)algo; - /* Derive it from public key point Q, which is 1 byte + x + y . */ - return (mpi_get_nbits (pkey[1]) / (8*2)) * 8; + + return mpi_get_nbits (pkey[0]); } @@ -1759,20 +1632,20 @@ run_selftests (int algo, int extended, selftest_report_func_t report) static const char *ecdsa_names[] = { "ecdsa", - "ecdh", - "ecc", /* Only here, for the minimum number of public parameters (= 2) */ + "ecc", NULL, }; static const char *ecdh_names[] = { "ecdh", + "ecc", NULL, }; gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = { "ECDSA", ecdsa_names, - "cq", "cqd", "", "rs", "cq", + "pabgnq", "pabgnqd", "", "rs", "pabgnq", GCRY_PK_USAGE_SIGN, ecc_generate, ecc_check_secret_key, @@ -1786,7 +1659,7 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = gcry_pk_spec_t _gcry_pubkey_spec_ecdh = { "ECDH", ecdh_names, - "cqp", "cqpd", "ab", "", "cqp", + "pabgnq", "pabgnqd", "", "rs", "pabgnq", GCRY_PK_USAGE_ENCR, ecc_generate, ecc_check_secret_key, commit 55563efccdafc8fb470cab0cae6d186147cc09b6 Merge: 2089236 f4786ac Author: Werner Koch Date: Thu Jan 27 06:51:04 2011 +0100 Merge commit 'f4786ac' into ECC-INTEGRATION-1-5 commit f4786ac5fe01ba111eee27d1a1e9f3d40a9fac02 Author: Werner Koch Date: Thu Jan 27 06:47:06 2011 +0100 Extend ignore file for non-vpath builds diff --git a/.gitignore b/.gitignore index 05033b3..ec7f8bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,83 @@ +*.lo +*.o +.deps/ +.libs/ +po/*.gmo +po/messages.mo /aclocal.m4 /autom4te.cache /config.h.in +/config.h +/config.log +/config.status /configure -Makefile.in +/libtool +/stamp-h1 +/Makefile.in +cipher/Makefile.in +compat/Makefile.in +doc/Makefile.in +m4/Makefile.in +mpi/Makefile.in +random/Makefile.in +src/Makefile.in +tests/Makefile.in +/Makefile +m4/Makefile +cipher/Makefile +cipher/libcipher.la +compat/Makefile +compat/libcompat.la doc/gcrypt.info doc/stamp-vti doc/version.texi +doc/Makefile +doc/fips-fsm.eps +doc/fips-fsm.pdf +doc/fips-fsm.png +doc/libgcrypt-modules.eps +doc/libgcrypt-modules.pdf +doc/libgcrypt-modules.png +mpi/Makefile +mpi/asm-syntax.h +mpi/libmpi.la +mpi/mod-source-info.h +mpi/mpi-asm-defs.h +mpi/mpih-add1-asm.S +mpi/mpih-lshift-asm.S +mpi/mpih-mul1-asm.S +mpi/mpih-mul2-asm.S +mpi/mpih-mul3-asm.S +mpi/mpih-rshift-asm.S +mpi/mpih-sub1-asm.S +mpi/sysdep.h +random/Makefile +random/librandom.la +src/Makefile +src/dumpsexp +src/gcrypt.h +src/hmac256 +src/libgcrypt-config +src/libgcrypt.la +src/versioninfo.rc +tests/Makefile +tests/ac +tests/ac-data +tests/ac-schemes +tests/aeswrap +tests/basic +tests/benchmark +tests/fips186-dsa +tests/fipsdrv +tests/hmac +tests/keygen +tests/keygrip +tests/mpitests +tests/prime +tests/pubkey +tests/random +tests/register +tests/rsacvt +tests/t-mpi-bit +tests/tsexp +tests/version commit 2089236f5713118e8adbaf8482730e3f2c556c1a Author: Werner Koch Date: Wed Jan 26 19:26:38 2011 +0100 Begin of changing the ECDH API. diff --git a/cipher/ChangeLog b/cipher/ChangeLog index 1b3694f..f38c818 100644 --- a/cipher/ChangeLog +++ b/cipher/ChangeLog @@ -1,3 +1,10 @@ +2011-01-26 Werner Koch + + * pubkey.c (sexp_to_key): Revert to pre-ECDH integration state. + Allow for ecdh. + * ecc.c (ecc_get_param): Revert to pre-ECDH integration state. + (compute_keygrip): Revert to 6 parameter version. + 2010-08-19 Werner Koch * cipher.c (gcry_cipher_open): Remove double release of the module. @@ -3979,7 +3986,7 @@ Mon Feb 16 10:08:47 1998 Werner Koch (wk at isil.d.shuttle.de) Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without diff --git a/cipher/ecc.c b/cipher/ecc.c index aa0cd6a..9ec4bb6 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -1137,16 +1137,11 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, /* Parse the optional transient-key flag. */ l1 = gcry_sexp_find_token (genparms, "transient-key", 0); - if( l1 ) { - const char *s; - s = _gcry_sexp_nth_string (l1, 1); - if( s && strcmp( s, "1" )==0 ) - transient_key = 1; - gcry_sexp_release (l1); - if (DBG_CIPHER) - log_debug ("ecgen 'transient-key' parameter supplied, value=%d\n", - transient_key); - } + if (l1) + { + transient_key = 1; + gcry_sexp_release (l1); + } /* Parse the "KEK parameters" parameter. */ l1 = gcry_sexp_find_token (genparms, "kek-params", 0); @@ -1154,14 +1149,16 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, { kek_params = gcry_sexp_nth_mpi (l1, 1, 0); gcry_sexp_release (l1); - if (!kek_params) { - log_debug( "ecgen failed to parse 'kek-params'\n" ); - return GPG_ERR_INV_OBJ; /* No curve name or value too large. */ - } - if (DBG_CIPHER) { - log_debug( "ecgen 'kek-params' parameter supplied\n" ); - log_mpidump ("ecgen DH kek-param", kek_params); - } + if (!kek_params) + { + log_debug( "ecgen failed to parse 'kek-params'\n" ); + return GPG_ERR_INV_OBJ; /* No value for kek-params. */ + } + if (DBG_CIPHER) + { + log_debug ("ecgen 'kek-params' parameter supplied\n" ); + log_mpidump ("ecgen DH kek-param", kek_params); + } } } @@ -1235,14 +1232,6 @@ ecc_generate (int algo, unsigned int nbits, unsigned long evalue, } -#if 0 -/* Need to be implemented, if called neeeded. The issue is that the - * purpose of this function is to return the information about the - * curve that is beyond the information present in the public key. In - * particular, the pkey size is now just 2, while we may need to - * return E.a, E.b, E.p, E.n, E.g, type of the curve, at the minimum. - * This information is readily available for well-known named curves. - */ /* Return the parameters of the curve NAME. */ static gcry_err_code_t ecc_get_param (const char *name, gcry_mpi_t *pkey) @@ -1265,17 +1254,15 @@ ecc_get_param (const char *name, gcry_mpi_t *pkey) _gcry_mpi_ec_free (ctx); point_free (&E.G); - pkey[0] = name_oid_to_mpi( E.name_oid ); - pkey[1] = E.p; - pkey[2] = E.a; - pkey[3] = E.b; - pkey[4] = ec2os (g_x, g_y, E.p); - pkey[5] = E.n; - pkey[6] = NULL; + pkey[0] = E.p; + pkey[1] = E.a; + pkey[2] = E.b; + pkey[3] = ec2os (g_x, g_y, E.p); + pkey[4] = E.n; + pkey[5] = NULL; return 0; } -#endif static gcry_err_code_t @@ -1616,19 +1603,19 @@ ecc_get_nbits (int algo, gcry_mpi_t *pkey) static gpg_err_code_t compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) { -#define N_ECC_PUBKEY_COMPONENETS 2 - static const char names[] = "cq"; +#define N_COMPONENTS 6 + static const char names[N_COMPONENTS+1] = "pabgnq"; gpg_err_code_t ec = 0; gcry_sexp_t l1; - gcry_mpi_t values[N_ECC_PUBKEY_COMPONENETS]; + gcry_mpi_t values[N_COMPONENTS]; int idx; /* Clear the values for easier error cleanup. */ - for (idx=0; idx < sizeof(values)/sizeof(values[0]); idx++) + for (idx=0; idx < N_COMPONENTS; idx++) values[idx] = NULL; - /* Fill values with all available parameters. */ - for (idx=0; idx < sizeof(values)/sizeof(values[0]); idx++) + /* Fill values with all provided parameters. */ + for (idx=0; idx < N_COMPONENTS; idx++) { l1 = gcry_sexp_find_token (keyparam, names+idx, 1); if (l1) @@ -1643,18 +1630,15 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) } } -#if 0 - /* Not used now: curve name (DER OID of the name, actually) is - always hashed above. */ /* Check whether a curve parameter is available and use that to fill in missing values. */ l1 = gcry_sexp_find_token (keyparam, "curve", 5); if (l1) { char *curve; - gcry_mpi_t tmpvalues[N_ECC_PUBKEY_COMPONENETS]; + gcry_mpi_t tmpvalues[N_COMPONENTS]; - for (idx = 0; idx < sizeof(tmpvalues)/sizeof(tmpvalues[0]); idx++) + for (idx = 0; idx < N_COMPONENTS; idx++) tmpvalues[idx] = NULL; curve = _gcry_sexp_nth_string (l1, 1); @@ -1668,7 +1652,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) if (ec) goto leave; - for (idx = 0; idx < sizeof(values)/sizeof(values[0]); idx++) + for (idx = 0; idx < N_COMPONENTS; idx++) { if (!values[idx]) values[idx] = tmpvalues[idx]; @@ -1676,12 +1660,11 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) mpi_free (tmpvalues[idx]); } } -#endif /* Check that all parameters are known and normalize all MPIs (that should not be required but we use an internal function later and thus we better make 100% sure that they are normalized). */ - for (idx = 0; idx < sizeof(values)/sizeof(values[0]); idx++) + for (idx = 0; idx < N_COMPONENTS; idx++) if (!values[idx]) { ec = GPG_ERR_NO_OBJ; @@ -1691,7 +1674,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) _gcry_mpi_normalize (values[idx]); /* Hash them all. */ - for (idx = 0; idx < sizeof(values)/sizeof(values[0]); idx++) + for (idx = 0; idx < N_COMPONENTS; idx++) { char buf[30]; unsigned char *rawmpi; @@ -1711,11 +1694,11 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) } leave: - for (idx = 0; idx < sizeof(values)/sizeof(values[0]); idx++) + for (idx = 0; idx < N_COMPONENTS; idx++) _gcry_mpi_release (values[idx]); return ec; -#undef N_ECC_PUBKEY_COMPONENETS +#undef N_COMPONENTS } @@ -1820,5 +1803,5 @@ pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = run_selftests, ecc_generate_ext, compute_keygrip, - NULL /* ecc_get_param */ + ecc_get_param }; diff --git a/cipher/pubkey.c b/cipher/pubkey.c index 64ae1a0..2861d29 100644 --- a/cipher/pubkey.c +++ b/cipher/pubkey.c @@ -950,6 +950,7 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, * openpgp-elg * openpgp-elg-sig * ecdsa + * ecdh * Provide a SE with the first element be either "private-key" or * or "public-key". It is followed by a list with its first element * be one of the above algorithm identifiers and the remaning @@ -983,7 +984,7 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, gcry_module_t module; gcry_pk_spec_t *pubkey; pk_extra_spec_t *extraspec; - /* FIXME: Why has this been removed? int is_ecc; * + int is_ecc; /* Check that the first element is valid. */ list = gcry_sexp_find_token (sexp, @@ -1011,7 +1012,9 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, with a key is compatible with an application of the key (signing, encryption). For RSA this is easy, but ECC is the first algorithm which has many flavours. */ - /* is_ecc = ( !strcmp (name, "ecdsa") || !strcmp (name, "ecc") ); */ + is_ecc = ( !strcmp (name, "ecdsa") + || !strcmp (name, "ecdh") + || !strcmp (name, "ecc") ); gcry_free (name); if (!module) @@ -1031,10 +1034,9 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, err = gpg_err_code_from_errno (errno); if (!err) { - /* FIXME: Removing this ECC case changes the ABI; we can't do it. */ - /* if (is_ecc) */ - /* err = sexp_elements_extract_ecc (list, elems, array, extraspec); */ - /* else */ + if (is_ecc) + err = sexp_elements_extract_ecc (list, elems, array, extraspec); + else err = sexp_elements_extract (list, elems, array, pubkey->name); } ----------------------------------------------------------------------- Summary of changes: .gitignore | 83 ++++++++ NEWS | 2 + cipher/ChangeLog | 49 +++++- cipher/ecc.c | 618 +++++++++++++++++++++--------------------------------- cipher/pubkey.c | 41 +++-- src/ChangeLog | 4 + src/sexp.c | 90 ++++++--- 7 files changed, 465 insertions(+), 422 deletions(-) create mode 100644 .gitignore hooks/post-receive -- The GNU crypto library http://git.gnupg.org