From cvs at cvs.gnupg.org Thu May 1 06:11:37 2014 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Thu, 01 May 2014 06:11:37 +0200 Subject: [git] Poldi - branch, master, updated. release-0.4.1-22-gfbaf642 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 "PAM for the OpenPGP card". The branch, master has been updated via fbaf642629b4a8b9e2e3b50ec9d0a98e894b7bcf (commit) via 51ff0fe77a07a4a7386bda2a520e35b90d3a4611 (commit) via afa739f1e63fa3959f974fa3c196e9449d66864e (commit) via 31bd644dab64a72bcbfec8bf71225b0264408b56 (commit) via 123b9dc89892a18ca91d7daf675b8dab89f56a5d (commit) via 90f8fe57c85b326b047f605dcb4b8cd9ae3486a6 (commit) from bfb6284a6d1f4a8557b4ac6905c2ce88fa223979 (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 fbaf642629b4a8b9e2e3b50ec9d0a98e894b7bcf Author: NIIBE Yutaka Date: Wed Apr 30 17:15:59 2014 +0900 * src/pam/auth-method-localdb/auth-localdb.c (auth_method_localdb_auth_do): Bug fix, use ->loghandle. diff --git a/src/pam/auth-method-localdb/auth-localdb.c b/src/pam/auth-method-localdb/auth-localdb.c index 6027ee1..0c65817 100644 --- a/src/pam/auth-method-localdb/auth-localdb.c +++ b/src/pam/auth-method-localdb/auth-localdb.c @@ -117,7 +117,7 @@ auth_method_localdb_auth_do (poldi_ctx_t ctx, username = username_desired; if (ctx->debug) - log_msg_debug (ctx->conv, + log_msg_debug (ctx->loghandle, _("Trying authentication as user `%s'..."), username); if (!ctx->quiet) conv_tell (ctx->conv, commit 51ff0fe77a07a4a7386bda2a520e35b90d3a4611 Author: NIIBE Yutaka Date: Wed Apr 30 17:15:11 2014 +0900 * src/pam/Makefile.am (pam_poldi.so): Use LDFLAGS and GCC. diff --git a/src/pam/Makefile.am b/src/pam/Makefile.am index a056613..968fb71 100644 --- a/src/pam/Makefile.am +++ b/src/pam/Makefile.am @@ -61,7 +61,7 @@ libpam_poldi_a_SOURCES = \ pam_poldi.so: libpam_poldi.a $(AUTH_METHODS_LIBS) auth-support/libpam-poldi-auth-support.a \ ../scd/libscd_shared.a ../util/libpoldi-util_shared.a - gcc -shared -o pam_poldi.so -Wl,-u,pam_sm_authenticate \ + $(CC) $(LDFLAGS) -shared -o pam_poldi.so -Wl,-u,pam_sm_authenticate \ libpam_poldi.a \ $(AUTH_METHODS_LIBS) auth-support/libpam-poldi-auth-support.a \ ../scd/libscd_shared.a ../util/libpoldi-util_shared.a ../assuan/libassuan.a \ commit afa739f1e63fa3959f974fa3c196e9449d66864e Author: NIIBE Yutaka Date: Wed Apr 30 17:07:44 2014 +0900 * src/pam/auth-support/getpin-cb.c (query_user): Remove checking of digits. Change error message when it's too short. diff --git a/src/pam/auth-support/getpin-cb.c b/src/pam/auth-support/getpin-cb.c index 10acbe7..5dfba9a 100644 --- a/src/pam/auth-support/getpin-cb.c +++ b/src/pam/auth-support/getpin-cb.c @@ -81,9 +81,10 @@ query_user (poldi_ctx_t ctx, const char *info, char *pin, size_t pin_size) Shouldn't they be done in scdaemon itself? -mo */ if (strlen (buffer) < 6) /* FIXME? is it really minimum of 6 bytes? */ - log_msg_error (ctx->loghandle, _("invalid PIN")); - else if (!all_digitsp (buffer)) - log_msg_error (ctx->loghandle, _("invalid characters in PIN")); + { + log_msg_error (ctx->loghandle, _("PIN too short")); + conv_tell (ctx->conv, "%s", _("PIN too short")); + } else break; } commit 31bd644dab64a72bcbfec8bf71225b0264408b56 Author: NIIBE Yutaka Date: Wed Apr 30 16:44:19 2014 +0900 * MIGRATION, TODO: Apply documentation change from Debian. diff --git a/MIGRATION b/MIGRATION index 2c33dbc..d5ee697 100644 --- a/MIGRATION +++ b/MIGRATION @@ -51,3 +51,5 @@ or greater. - "fake-wait-for-card" - "require-card-switch" - "wait-timeout" + - "try_pin" + - "quiet" diff --git a/TODO b/TODO index c62faea..fe509a1 100644 --- a/TODO +++ b/TODO @@ -2,6 +2,9 @@ Final: * allow for Dirmngr to be started on demand (in pipe mode) (NO <- Why?!) Low priority: +* allow user to skip card authentication without submitting a wrong + PIN to the card, e.g. by entering an empty PIN? Return + PAM_CRED_INSUFFICIENT in that case? PAM_AUTHINFO_UNAVAIL? PAM_AUTH_ERR? * figure out what exactly the dependencies on the OpenPGP smartcard are. * improve doc * work on MIGRATION text commit 123b9dc89892a18ca91d7daf675b8dab89f56a5d Author: NIIBE Yutaka Date: Wed Apr 30 16:43:03 2014 +0900 * conf/Makefile.am: Add scdaemon.conf installation. * conf/scdaemon.conf.skel: New. diff --git a/conf/Makefile.am b/conf/Makefile.am index 373d70d..47a5886 100644 --- a/conf/Makefile.am +++ b/conf/Makefile.am @@ -33,5 +33,11 @@ install-conf-skeleton: install -m 644 -T $(top_srcdir)/conf/poldi.conf.skel \ $(DESTDIR)$(POLDI_CONF_DIRECTORY)/poldi.conf; \ fi + if test -e $(DESTDIR)$(POLDI_CONF_DIRECTORY)/scdaemon.conf; then \ + echo "$(DESTDIR)$(POLDI_CONF_DIRECTORY)/scdaemon.conf exists, doing nothing here"; \ + else \ + install -m 644 -T $(top_srcdir)/conf/scdaemon.conf.skel \ + $(DESTDIR)$(POLDI_CONF_DIRECTORY)/scdaemon.conf; \ + fi -EXTRA_DIST = poldi.conf.skel users.skel README.keys +EXTRA_DIST = poldi.conf.skel users.skel scdaemon.conf.skel README.keys diff --git a/conf/scdaemon.conf.skel b/conf/scdaemon.conf.skel new file mode 100644 index 0000000..9c006a9 --- /dev/null +++ b/conf/scdaemon.conf.skel @@ -0,0 +1,11 @@ +# +# Disable internal CCID driver (but always use PC/SC driver) +# disable-ccid +# +# Useful options to debug: +# +# debug-level guru +# debug-all +# log-file /tmp/scd.log +# debug-ccid-driver +# commit 90f8fe57c85b326b047f605dcb4b8cd9ae3486a6 Author: NIIBE Yutaka Date: Wed Apr 30 16:39:29 2014 +0900 * conf/poldi.conf.skel (scdaemon-program): Change the path. diff --git a/conf/poldi.conf.skel b/conf/poldi.conf.skel index 58967b3..3fed157 100644 --- a/conf/poldi.conf.skel +++ b/conf/poldi.conf.skel @@ -11,4 +11,4 @@ log-file /var/log/poldi debug # Specify SCDaemon executable -scdaemon-program /usr/bin/scdaemon +scdaemon-program /usr/lib/gnupg2/scdaemon ----------------------------------------------------------------------- Summary of changes: MIGRATION | 2 ++ TODO | 3 +++ conf/Makefile.am | 8 +++++++- conf/poldi.conf.skel | 2 +- conf/scdaemon.conf.skel | 11 +++++++++++ src/pam/Makefile.am | 2 +- src/pam/auth-method-localdb/auth-localdb.c | 2 +- src/pam/auth-support/getpin-cb.c | 7 ++++--- 8 files changed, 30 insertions(+), 7 deletions(-) create mode 100644 conf/scdaemon.conf.skel hooks/post-receive -- PAM for the OpenPGP card http://git.gnupg.org From cvs at cvs.gnupg.org Thu May 1 07:00:10 2014 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Thu, 01 May 2014 07:00:10 +0200 Subject: [git] Poldi - branch, master, updated. release-0.4.1-28-gda5d8f0 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 "PAM for the OpenPGP card". The branch, master has been updated via da5d8f0650ec99891dacd22c83d809c2c598a6d2 (commit) via 99618ca58f766fcd813f9d31f584a75a14f81611 (commit) via f6a3c0a443783b5923b32d28fd67900912b6ae7d (commit) via 5b5da41531da1304e643c93130139259b0d3fd40 (commit) via 2e1ef35d470d50f9888029fa051e8eb2c14bf0fa (commit) via 4eb63a2a020d3dd6796db0e259e0b431701975f4 (commit) from fbaf642629b4a8b9e2e3b50ec9d0a98e894b7bcf (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 da5d8f0650ec99891dacd22c83d809c2c598a6d2 Author: NIIBE Yutaka Date: Thu May 1 14:01:39 2014 +0900 * src/scd/scd.c (unescape_status_string, unhexify_fpr): Fix type qualifier. diff --git a/src/scd/scd.c b/src/scd/scd.c index f0b6d35..d54b47e 100644 --- a/src/scd/scd.c +++ b/src/scd/scd.c @@ -449,7 +449,7 @@ scd_set_pincb (scd_context_t scd_ctx, silently be replaced by a 0xFF. Function returns NULL to indicate an out of memory status. */ static char * -unescape_status_string (const unsigned char *s) +unescape_status_string (const char *s) { char *buffer, *d; @@ -487,7 +487,7 @@ unescape_status_string (const unsigned char *s) /* Take a 20 byte hexencoded string and put it into the the provided 20 byte buffer FPR in binary format. */ static int -unhexify_fpr (const char *hexstr, unsigned char *fpr) +unhexify_fpr (const char *hexstr, char *fpr) { const char *s; int n; commit 99618ca58f766fcd813f9d31f584a75a14f81611 Author: NIIBE Yutaka Date: Thu May 1 14:00:52 2014 +0900 * src/pam/auth-support/getpin-cb.c (all_digitsp): Remove. (strcpy_escaped): Fix type qualifier. diff --git a/src/pam/auth-support/getpin-cb.c b/src/pam/auth-support/getpin-cb.c index 5dfba9a..c5d7ba8 100644 --- a/src/pam/auth-support/getpin-cb.c +++ b/src/pam/auth-support/getpin-cb.c @@ -46,17 +46,6 @@ #include "getpin-cb.h" - -/* Returns TRUE if the string S contains only decimal digits, FALSE - otherwise. */ -static int -all_digitsp (const char *s) -{ - for (; *s && *s >= '0' && *s <= '9'; s++) - ; - return !*s; -} - /* Query the user through PAM for his PIN. Display INFO to the user. Store the retrieved pin in PIN, which is of size PIN_SIZE. If it does not fit, return error. */ @@ -130,7 +119,7 @@ keypad_mode_leave (poldi_ctx_t ctx) /* Note, that it is sufficient to allocate the target string D as long as the source string S, i.e.: strlen(s)+1; */ static void -strcpy_escaped (char *d, const unsigned char *s) +strcpy_escaped (char *d, const char *s) { while (*s) { commit f6a3c0a443783b5923b32d28fd67900912b6ae7d Author: NIIBE Yutaka Date: Thu May 1 14:00:26 2014 +0900 * src/ctrl/poldi-ctrl.c (main): Argv type fix. diff --git a/src/ctrl/poldi-ctrl.c b/src/ctrl/poldi-ctrl.c index f595f01..3dc22f5 100644 --- a/src/ctrl/poldi-ctrl.c +++ b/src/ctrl/poldi-ctrl.c @@ -244,7 +244,7 @@ i18n_cb (void *cookie, const char *msg) /* Main. */ int -main (int argc, char **argv) +main (int argc, const char **argv) { simpleparse_handle_t parsehandle; unsigned int ncommands; commit 5b5da41531da1304e643c93130139259b0d3fd40 Author: NIIBE Yutaka Date: Thu May 1 13:59:48 2014 +0900 * src/assuan/assuan-handler.c (assuan_process_done): Bug fix using code. diff --git a/src/assuan/assuan-handler.c b/src/assuan/assuan-handler.c index b940bfd..d60e380 100644 --- a/src/assuan/assuan-handler.c +++ b/src/assuan/assuan-handler.c @@ -558,7 +558,7 @@ assuan_process_done (assuan_context_t ctx, int rc) { /* Assume this is an libgpg-error. */ sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s", - rc, ebuf, esrc, + code, ebuf, esrc, text? " - ":"", text?text:""); } else @@ -593,7 +593,7 @@ assuan_process_done (assuan_context_t ctx, int rc) gpg_strerror_r (rc, ebuf, sizeof ebuf ); sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s", - rc, + code, ebuf, gpg_strsource (rc), text? " - ":"", text?text:""); commit 2e1ef35d470d50f9888029fa051e8eb2c14bf0fa Author: NIIBE Yutaka Date: Thu May 1 13:59:02 2014 +0900 * doc/gpl.texi: Use @center for Info. diff --git a/doc/gpl.texi b/doc/gpl.texi index ca0508f..92d087c 100644 --- a/doc/gpl.texi +++ b/doc/gpl.texi @@ -12,7 +12,12 @@ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @end display + at iftex @appendixsubsec Preamble + at end iftex + at ifinfo + at center Preamble + at end ifinfo The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public commit 4eb63a2a020d3dd6796db0e259e0b431701975f4 Author: NIIBE Yutaka Date: Thu May 1 13:58:11 2014 +0900 * configure.ac, m4/po.m4, src/assuan/Makefile.am: Update for newer autotools. diff --git a/configure.ac b/configure.ac index c901520..0fd6acd 100644 --- a/configure.ac +++ b/configure.ac @@ -23,11 +23,12 @@ AC_PREREQ(2.52) min_automake_version="1.7.9" # Version number: Remember to change it immediately *after* a release. -# Add a "-cvs" prefix for non-released code. -AC_INIT(poldi, 0.4.2-cvs, gnupg-devel at gnupg.org) - -PACKAGE=$PACKAGE_NAME -VERSION=$PACKAGE_VERSION +# Add a "-git" prefix for non-released code. +AC_INIT([poldi], [0.4.2-git], [gnupg-devel at gnupg.org]) +AC_CONFIG_SRCDIR(src/pam/pam_poldi.c) +AC_CONFIG_HEADERS(config.h) +AC_CANONICAL_TARGET +AM_INIT_AUTOMAKE NEED_LIBGCRYPT_VERSION=0 NEED_GPG_ERROR_VERSION=0.7 @@ -35,12 +36,6 @@ NEED_GPG_ERROR_VERSION=0.7 NEED_KSBA_API=1 NEED_KSBA_VERSION=1.0.2 - -AC_CONFIG_SRCDIR(src/pam/pam_poldi.c) -AM_CONFIG_HEADER(config.h) -AC_CANONICAL_TARGET -AM_INIT_AUTOMAKE($PACKAGE, $VERSION) - POLDI_CONF_DIRECTORY="${sysconfdir}/poldi" AC_SUBST(POLDI_CONF_DIRECTORY) @@ -63,8 +58,6 @@ POLDI_ENABLE_FEATURE(enable_auth_x509, yes, x509-auth, support for X509 authenti POLDI_ENABLE_FEATURE(enable_auth_localdb, yes, localdb-auth, support for local-db authentication) AC_SUBST(PACKAGE) AC_SUBST(VERSION) -AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package]) -AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version of this package]) AC_DEFINE_UNQUOTED(PACKAGE_BUGREPORT, "$PACKAGE_BUGREPORT", [Bug report address]) AC_DEFINE_UNQUOTED(NEED_LIBGCRYPT_VERSION, "$NEED_LIBGCRYPT_VERSION", diff --git a/m4/po.m4 b/m4/po.m4 index 0734762..f7c9c06 100644 --- a/m4/po.m4 +++ b/m4/po.m4 @@ -24,7 +24,7 @@ AC_DEFUN([AM_PO_SUBDIRS], [ AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl - AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake + AC_REQUIRE([AC_PROG_MKDIR_P])dnl AC_REQUIRE([AM_NLS])dnl dnl Release version of the gettext macros. This is used to ensure that diff --git a/src/assuan/Makefile.am b/src/assuan/Makefile.am index 56e2eed..f10f7a0 100644 --- a/src/assuan/Makefile.am +++ b/src/assuan/Makefile.am @@ -20,7 +20,7 @@ # Modified for Poldi. Based von libassuans Makefile.am. EXTRA_DIST = mkerrors -INCLUDES = -I.. -I$(top_srcdir)/include +AM_CPPFLAGS = -I.. -I$(top_srcdir)/include BUILT_SOURCES = assuan-errors.c MOSTLYCLEANFILES = assuan-errors.c ----------------------------------------------------------------------- Summary of changes: configure.ac | 19 ++++++------------- doc/gpl.texi | 5 +++++ m4/po.m4 | 2 +- src/assuan/Makefile.am | 2 +- src/assuan/assuan-handler.c | 4 ++-- src/ctrl/poldi-ctrl.c | 2 +- src/pam/auth-support/getpin-cb.c | 13 +------------ src/scd/scd.c | 4 ++-- 8 files changed, 19 insertions(+), 32 deletions(-) hooks/post-receive -- PAM for the OpenPGP card http://git.gnupg.org From cvs at cvs.gnupg.org Thu May 1 10:11:59 2014 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Thu, 01 May 2014 10:11:59 +0200 Subject: [git] Poldi - branch, master, updated. release-0.4.1-30-gba7154b 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 "PAM for the OpenPGP card". The branch, master has been updated via ba7154bea83ba8b4888b9f733ee0de71deb6f3e4 (commit) via 61ae5472639e1ee5d751db94a55528dfc640a9d0 (commit) from da5d8f0650ec99891dacd22c83d809c2c598a6d2 (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 ba7154bea83ba8b4888b9f733ee0de71deb6f3e4 Author: NIIBE Yutaka Date: Thu May 1 17:13:44 2014 +0900 * configure.ac: Version number. * po/poldi.pot, po/de.po: Updated. diff --git a/configure.ac b/configure.ac index 0fd6acd..4e0b53a 100644 --- a/configure.ac +++ b/configure.ac @@ -23,8 +23,8 @@ AC_PREREQ(2.52) min_automake_version="1.7.9" # Version number: Remember to change it immediately *after* a release. -# Add a "-git" prefix for non-released code. -AC_INIT([poldi], [0.4.2-git], [gnupg-devel at gnupg.org]) +# Add a ".git" postfix for non-released code. +AC_INIT([poldi], [0.4.2.git], [gnupg-devel at gnupg.org]) AC_CONFIG_SRCDIR(src/pam/pam_poldi.c) AC_CONFIG_HEADERS(config.h) AC_CANONICAL_TARGET diff --git a/po/de.po b/po/de.po index 4270537..6314582 100644 --- a/po/de.po +++ b/po/de.po @@ -7,10 +7,11 @@ msgid "" msgstr "" "Project-Id-Version: poldi 0.4-cvs\n" "Report-Msgid-Bugs-To: gnupg-devel at gnupg.org\n" -"POT-Creation-Date: 2009-08-08 18:44+0200\n" +"POT-Creation-Date: 2014-05-01 15:45+0900\n" "PO-Revision-Date: 2009-08-08 19:47+0200\n" "Last-Translator: Moritz Schulte \n" "Language-Team: LANGUAGE \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -115,29 +116,25 @@ msgid "failed to convert key from `%s' into S-Expression: %s\n" msgstr "" "konnte Schl?ssel aus '%s' nicht in eine S-Expression konvertieren: %s\n" -#: src/pam/auth-support/getpin-cb.c:84 -msgid "invalid PIN" -msgstr "ung?ltige PIN" - -#: src/pam/auth-support/getpin-cb.c:86 -msgid "invalid characters in PIN" -msgstr "ung?ltige Zeichen in PIN" +#: src/pam/auth-support/getpin-cb.c:74 src/pam/auth-support/getpin-cb.c:75 +msgid "PIN too short" +msgstr "" -#: src/pam/auth-support/getpin-cb.c:93 +#: src/pam/auth-support/getpin-cb.c:83 msgid "PIN too long for buffer!" msgstr "PIN zu lang f?r Puffer" -#: src/pam/auth-support/getpin-cb.c:214 +#: src/pam/auth-support/getpin-cb.c:204 #, c-format msgid "getpin_cb called with flags set in info string `%s'\n" msgstr "getpin-Callback mit nicht unterst?tzten Flags in '%s' aufgerufen\n" -#: src/pam/auth-support/getpin-cb.c:224 +#: src/pam/auth-support/getpin-cb.c:214 #, c-format msgid "frob_info_msg failed for info msg of size %u\n" msgstr "frob_info_msg fehlgeschlagen f?r eine Nachricht der L?nge %u\n" -#: src/pam/auth-support/getpin-cb.c:238 src/pam/auth-support/getpin-cb.c:257 +#: src/pam/auth-support/getpin-cb.c:228 src/pam/auth-support/getpin-cb.c:247 msgid "Please enter the PIN:" msgstr "Bitte PIN eingeben:" @@ -270,15 +267,15 @@ msgid "" "failed to initialize parsing of configuration file for authentication method " "%s: %s" msgstr "" -"konnte Auswertung der Konfigurationsdatei f?r die Authentifikationsmethode %" -"s nicht beginnen: %s" +"konnte Auswertung der Konfigurationsdatei f?r die Authentifikationsmethode " +"%s nicht beginnen: %s" #: src/pam/pam_poldi.c:509 #, c-format msgid "failed to parse configuration for authentication method %i: %s" msgstr "" -"konnte Konfigurationsdatei f?r die Authentifikationsmethode %i nicht lesen: %" -"s" +"konnte Konfigurationsdatei f?r die Authentifikationsmethode %i nicht lesen: " +"%s" #: src/pam/pam_poldi.c:528 msgid "failed to retrieve PAM conversation structure" @@ -400,6 +397,12 @@ msgstr "fehlendes notwendiges Argument f?r '%s'" msgid "too many arguments specified for option '%s'" msgstr "zu viele Argumente f?r Options '%s' angegeben" +#~ msgid "invalid PIN" +#~ msgstr "ung?ltige PIN" + +#~ msgid "invalid characters in PIN" +#~ msgstr "ung?ltige Zeichen in PIN" + #~ msgid "using system scdaemon; socket is '%s'" #~ msgstr "benutze System-Scdaaemon; Socket ist '%s'" diff --git a/po/poldi.pot b/po/poldi.pot index d257a9b..70426c5 100644 --- a/po/poldi.pot +++ b/po/poldi.pot @@ -6,12 +6,13 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: poldi 0.4.2-cvs\n" +"Project-Id-Version: poldi 0.4.2.git\n" "Report-Msgid-Bugs-To: gnupg-devel at gnupg.org\n" -"POT-Creation-Date: 2009-08-08 18:44+0200\n" +"POT-Creation-Date: 2014-05-01 15:45+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" @@ -112,29 +113,25 @@ msgstr "" msgid "failed to convert key from `%s' into S-Expression: %s\n" msgstr "" -#: src/pam/auth-support/getpin-cb.c:84 -msgid "invalid PIN" +#: src/pam/auth-support/getpin-cb.c:74 src/pam/auth-support/getpin-cb.c:75 +msgid "PIN too short" msgstr "" -#: src/pam/auth-support/getpin-cb.c:86 -msgid "invalid characters in PIN" -msgstr "" - -#: src/pam/auth-support/getpin-cb.c:93 +#: src/pam/auth-support/getpin-cb.c:83 msgid "PIN too long for buffer!" msgstr "" -#: src/pam/auth-support/getpin-cb.c:214 +#: src/pam/auth-support/getpin-cb.c:204 #, c-format msgid "getpin_cb called with flags set in info string `%s'\n" msgstr "" -#: src/pam/auth-support/getpin-cb.c:224 +#: src/pam/auth-support/getpin-cb.c:214 #, c-format msgid "frob_info_msg failed for info msg of size %u\n" msgstr "" -#: src/pam/auth-support/getpin-cb.c:238 src/pam/auth-support/getpin-cb.c:257 +#: src/pam/auth-support/getpin-cb.c:228 src/pam/auth-support/getpin-cb.c:247 msgid "Please enter the PIN:" msgstr "" commit 61ae5472639e1ee5d751db94a55528dfc640a9d0 Author: NIIBE Yutaka Date: Thu May 1 14:08:04 2014 +0900 add .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9e1c7bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +Makefile.in +aclocal.m4 +compile +config.guess +config.sub +depcomp +install-sh +missing +autom4te.cache/ +configure +config.h.in +doc/poldi.info* +doc/stamp-vti +doc/version.texi +po/*.gmo +po/stamp-po \ No newline at end of file ----------------------------------------------------------------------- Summary of changes: .gitignore | 16 ++++++++++++++++ configure.ac | 4 ++-- po/de.po | 35 +++++++++++++++++++---------------- po/poldi.pot | 21 +++++++++------------ 4 files changed, 46 insertions(+), 30 deletions(-) create mode 100644 .gitignore hooks/post-receive -- PAM for the OpenPGP card http://git.gnupg.org From cvs at cvs.gnupg.org Fri May 2 14:06:25 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Fri, 02 May 2014 14:06:25 +0200 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-402-g2def230 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 2def230231abd34f6012df284ab468321ffedc10 (commit) via 8412a5825c225c8ff14de3ffaad2e55e040b2eca (commit) via 84289e85c72ae58c321dfdb96816700a6b7f7122 (commit) from 8416c875a729426eae05ed1ca9f1ebcb933c246a (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 2def230231abd34f6012df284ab468321ffedc10 Author: Werner Koch Date: Fri May 2 14:07:03 2014 +0200 common: Fix test for openpgp_oid_is_ed25519. * common/t-openpgp-oid.c (test_openpgp_oid_is_ed25519): Add correct value. diff --git a/common/t-openpgp-oid.c b/common/t-openpgp-oid.c index d101b75..79e5a70 100644 --- a/common/t-openpgp-oid.c +++ b/common/t-openpgp-oid.c @@ -145,10 +145,15 @@ test_openpgp_oid_is_ed25519 (void) { 0, "0.0" }, { 0, "1.3.132.0.35" }, { 0, "1.3.6.1.4.1.3029.1.5.0" }, - { 1, "1.3.6.1.4.1.3029.1.5.1" }, + { 0, "1.3.6.1.4.1.3029.1.5.1" }, /* Used during Libgcrypt development. */ { 0, "1.3.6.1.4.1.3029.1.5.2" }, { 0, "1.3.6.1.4.1.3029.1.5.1.0" }, { 0, "1.3.6.1.4.1.3029.1.5" }, + { 0, "1.3.6.1.4.1.11591.15.0" }, + { 1, "1.3.6.1.4.1.11591.15.1" }, /* Your the one we want. */ + { 0, "1.3.6.1.4.1.11591.15.2" }, + { 0, "1.3.6.1.4.1.11591.15.1.0" }, + { 0, "1.3.6.1.4.1.11591.15" }, { 0, NULL }, }; gpg_error_t err; commit 8412a5825c225c8ff14de3ffaad2e55e040b2eca Author: Werner Koch Date: Fri May 2 10:33:19 2014 +0200 http: Revamp TLS API. * configure.ac (NEED_GNUTLS_VERSION): New. (HTTP_USE_GNUTLS, LIBGNUTLS_CFLAGS, LIBGNUTLS_LIBS): New ac_subst. * common/http.h (http_session_t): New. * common/http.c: Remove compatibility for gnutls < 3.0. (http_session_s): New. (cookie_s): Replace gnutls_session_t by http_session_t. (tls_callback, tls_ca_certlist): New variables. (my_socket_unref): Add preclose args. (my_npth_read, my_npth_write): New. (make_header_line): Fix bug using int* instead of char*. (http_register_tls_callback): New. (http_register_tls_ca): New. (http_session_new): New. (http_session_release): New. (http_get_header_names): New. (escape_data): Add hack to escape in forms mode. (send_request) [HTTP_USE_GNUTLS]: Support SNI. (send_request) [HTTP_USE_GNUTLS]: Fix use of make_header_line. (send_gnutls_bye): New. (cookie_close): Make use of preclose feature. (http_verify_server_credentials): New. (main) [TEST]: Remove test code. * common/t-http.c: New. * common/tls-ca.pem: New. * common/Makefile.am (tls_sources): New. Move http code to here. (libcommontls_a_SOURCES): New. (libcommontlsnpth_a_SOURCES): New. (EXTRA_DIST): Add tls-ca.pem (module_maint_tests): Add t-http. (t_http_SOURCES, t_http_CFLAGS, t_http_LDADD): New. * dirmngr/Makefile.am (dirmngr_LDADD): Add libcommontlsnpth. -- This new TLS API for http.c is much more flexible than the crude old hack. diff --git a/am/cmacros.am b/am/cmacros.am index 6ee4283..4b48560 100644 --- a/am/cmacros.am +++ b/am/cmacros.am @@ -75,3 +75,5 @@ resource_objs = # Convenience macros libcommon = ../common/libcommon.a libcommonpth = ../common/libcommonpth.a +libcommontls = ../common/libcommontls.a +libcommontlsnpth = ../common/libcommontlsnpth.a diff --git a/common/Makefile.am b/common/Makefile.am index f1cf28c..439c29b 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -20,9 +20,10 @@ EXTRA_DIST = mkstrtable.awk exaudit.awk exstatus.awk ChangeLog-2011 \ audit-events.h status-codes.h README.jnlib ChangeLog.jnlib \ - ChangeLog-2011.include w32info-rc.h.in gnupg.ico + ChangeLog-2011.include w32info-rc.h.in gnupg.ico tls-ca.pem -noinst_LIBRARIES = libcommon.a libcommonpth.a libgpgrl.a +noinst_LIBRARIES = libcommon.a libcommonpth.a libgpgrl.a \ + libcommontls.a libcommontlsnpth.a if !HAVE_W32CE_SYSTEM noinst_LIBRARIES += libsimple-pwquery.a endif @@ -88,7 +89,6 @@ common_sources = \ srv.h \ dns-cert.c dns-cert.h \ pka.c pka.h \ - http.c http.h \ localename.c \ session-env.c session-env.h \ userids.c userids.h \ @@ -97,6 +97,12 @@ common_sources = \ agent-opt.c \ helpfile.c +# Sources possible requiring a TLS library are put into a separate +# conveince library. +tls_sources = \ + http.c http.h + + # To make the code easier to read we have split home some code into # separate source files. if HAVE_W32_SYSTEM @@ -126,6 +132,12 @@ libcommonpth_a_SOURCES += srv.c endif libcommonpth_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS) +libcommontls_a_SOURCES = $(tls_sources) +libcommontls_a_CFLAGS = $(AM_CFLAGS) $(LIBGNUTLS_CFLAGS) -DWITHOUT_NPTH=1 + +libcommontlsnpth_a_SOURCES = $(tls_sources) +libcommontlsnpth_a_CFLAGS = $(AM_CFLAGS) $(LIBGNUTLS_CFLAGS) $(NPTH_CFLAGS) + if !HAVE_W32CE_SYSTEM libsimple_pwquery_a_SOURCES = \ simple-pwquery.c simple-pwquery.h asshelp.c asshelp.h @@ -170,11 +182,12 @@ module_tests = t-convert t-percent t-gettime t-sysutils t-sexputil \ if !HAVE_W32CE_SYSTEM module_tests += t-exechelp endif -module_maint_tests = t-helpfile t-b64 +module_maint_tests = t-helpfile t-b64 t-http t_common_ldadd = libcommon.a ../gl/libgnu.a \ - $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV) + $(LIBGCRYPT_LIBS) $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \ + $(LIBINTL) $(LIBICONV) # jnlib tests t_stringhelp_SOURCES = t-stringhelp.c $(t_jnlib_src) @@ -203,3 +216,8 @@ t_ssh_utils_LDADD = $(t_common_ldadd) t_dns_cert_LDADD = $(t_common_ldadd) $(DNSLIBS) t_mapstrings_LDADD = $(t_common_ldadd) t_zb32_LDADD = $(t_common_ldadd) + +# http tests +t_http_SOURCES = t-http.c +t_http_CFLAGS = $(t_common_cflags) $(LIBGNUTLS_CFLAGS) +t_http_LDADD = $(libcommontls) $(t_common_ldadd) $(LIBGNUTLS_LIBS) $(DNSLIBS) diff --git a/common/http.c b/common/http.c index 11a7130..e5516e8 100644 --- a/common/http.c +++ b/common/http.c @@ -39,8 +39,9 @@ - fixme: list other requirements. - - With HTTP_USE_GNUTLS support for https is provided (this also - requires estream). + - With HTTP_USE_GNUTLS or HTTP_USE_POLARSSL support for https is + provided (this also requires estream). + - With HTTP_NO_WSASTARTUP the socket initialization is not done under Windows. This is useful if the socket layer has already been initialized elsewhere. This also avoids the installation of @@ -81,20 +82,19 @@ # include #endif +#if defined (HTTP_USE_GNUTLS) && defined (HTTP_USE_POLARSSL) +# error Both, HTTP_USE_GNUTLS and HTTP_USE_POLARSSL, are defined. +#endif + #ifdef HTTP_USE_GNUTLS # include -/* For non-understandable reasons GNUTLS dropped the _t suffix from - all types. yes, ISO-C might be read as this but there are still - other name space conflicts and using _t is actually a Good - Thing. */ -typedef gnutls_session gnutls_session_t; -typedef gnutls_transport_ptr gnutls_transport_ptr_t; +# include #endif /*HTTP_USE_GNUTLS*/ - -#ifdef TEST -# undef USE_DNS_SRV +#ifdef HTTP_USE_POLARSSL +# error Support for PolarSSL has not yet been added #endif + #include "util.h" #include "i18n.h" #include "http.h" @@ -204,22 +204,36 @@ struct cookie_s /* Socket object or NULL if already closed. */ my_socket_t sock; - /* TLS session context or NULL if not used. */ - gnutls_session_t tls_session; + /* The session object or NULL if not used. */ + http_session_t session; + + /* True if TLS is to be used. */ + int use_tls; /* The remaining content length and a flag telling whether to use the content length. */ longcounter_t content_length; unsigned int content_length_valid:1; - - /* Flag to communicate with the close handler. */ - unsigned int keep_socket:1; }; typedef struct cookie_s *cookie_t; +/* The session object. */ +struct http_session_s +{ #ifdef HTTP_USE_GNUTLS -static gpg_error_t (*tls_callback) (http_t, gnutls_session_t, int); -#endif /*HTTP_USE_GNUTLS*/ + gnutls_certificate_credentials_t certcred; + gnutls_session_t tls_session; + struct { + int done; /* Verifciation has been done. */ + int rc; /* GnuTLS verification return code. */ + unsigned int status; /* Verification status. */ + } verify; + char *servername; /* Malloced server name. */ +#else + int dummy; +#endif +}; + /* An object to save header lines. */ @@ -243,7 +257,7 @@ struct http_context_s estream_t fp_write; void *write_cookie; void *read_cookie; - void *tls_context; + http_session_t session; parsed_uri_t uri; http_req_t req_type; char *buffer; /* Line buffer. */ @@ -253,6 +267,12 @@ struct http_context_s }; +/* The global callback for the verification fucntion. */ +static gpg_error_t (*tls_callback) (http_t, http_session_t, int); + +/* The list of files with trusted CA certificates. */ +static strlist_t tls_ca_certlist; + #if defined(HAVE_W32_SYSTEM) && !defined(HTTP_NO_WSASTARTUP) @@ -340,7 +360,7 @@ my_socket_ref (my_socket_t so) has no more references, close the socket and release the object. */ static void -my_socket_unref (my_socket_t so) +my_socket_unref (my_socket_t so, void (*preclose)(void*), void *preclosearg) { if (so) { @@ -349,6 +369,8 @@ my_socket_unref (my_socket_t so) /* lnr, so, so->fd, so->refcount); */ if (!so->refcount) { + if (preclose) + preclose (preclosearg); sock_close (so->fd); xfree (so); } @@ -357,6 +379,21 @@ my_socket_unref (my_socket_t so) /* #define my_socket_unref(a) _my_socket_unref ((a),__LINE__) */ +#if defined (USE_NPTH) && defined(HTTP_USE_GNUTLS) +static ssize_t +my_npth_read (gnutls_transport_ptr_t ptr, void *buffer, size_t size) +{ + return npth_read ((int)(unsigned long)ptr, buffer, size); +} +static ssize_t +my_npth_write (gnutls_transport_ptr_t ptr, const void *buffer, size_t size) +{ + return npth_write ((int)(unsigned long)ptr, buffer, size); +} +#endif /*USE_NPTH && HTTP_USE_GNUTLS*/ + + + /* This notification function is called by estream whenever stream is closed. Its purpose is to mark the closing in the handle so @@ -383,13 +420,13 @@ fp_onclose_notification (estream_t stream, void *opaque) */ static char * make_header_line (const char *prefix, const char *suffix, - const void *data, size_t len ) + const void *data, size_t len ) { static unsigned char bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; - const unsigned int *s = data; + const unsigned char *s = data; char *buffer, *p; buffer = xtrymalloc (strlen (prefix) + (len+2)/3*4 + strlen (suffix) + 1); @@ -402,6 +439,7 @@ make_header_line (const char *prefix, const char *suffix, *p++ = bintoasc[(((s[0] <<4)&060)|((s[1] >> 4)&017))&077]; *p++ = bintoasc[(((s[1]<<2)&074)|((s[2]>>6)&03))&077]; *p++ = bintoasc[s[2]&077]; + *p = 0; } if ( len == 2 ) { @@ -417,6 +455,7 @@ make_header_line (const char *prefix, const char *suffix, *p++ = '='; *p++ = '='; } + *p = 0; strcpy (p, suffix); return buffer; } @@ -424,17 +463,132 @@ make_header_line (const char *prefix, const char *suffix, +/* Register the global TLS callback fucntion. */ +void +http_register_tls_callback (gpg_error_t (*cb)(http_t, http_session_t, int)) +{ + tls_callback = cb; +} + + +/* Register a CA certificate for future use. The certificate is + expected to be in FNAME. PEM format is assume if FNAME has a + suffix of ".pem" */ void -http_register_tls_callback ( gpg_error_t (*cb) (http_t, void *, int) ) +http_register_tls_ca (const char *fname) +{ + strlist_t sl; + + sl = add_to_strlist (&tls_ca_certlist, fname); + if (*sl->d && !strcmp (sl->d + strlen (sl->d) - 4, ".pem")) + sl->flags = 1; +} + + +/* Create a new session object which is currently used to enable TLS + support. It may eventually allow reusing existing connections. */ +gpg_error_t +http_session_new (http_session_t *r_session, const char *tls_priority) { + gpg_error_t err; + http_session_t sess; + + *r_session = NULL; + + sess = xtrycalloc (1, sizeof *sess); + if (!sess) + return gpg_error_from_syserror (); + #ifdef HTTP_USE_GNUTLS - tls_callback = (gpg_error_t (*) (http_t, gnutls_session_t, int))cb; -#else - (void)cb; -#endif + { + const char *errpos; + int rc; + strlist_t sl; + + rc = gnutls_certificate_allocate_credentials (&sess->certcred); + if (rc < 0) + { + log_error ("gnutls_certificate_allocate_credentials failed: %s\n", + gnutls_strerror (rc)); + err = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + + for (sl = tls_ca_certlist; sl; sl = sl->next) + { + rc = gnutls_certificate_set_x509_trust_file + (sess->certcred, sl->d, + (sl->flags & 1)? GNUTLS_X509_FMT_PEM : GNUTLS_X509_FMT_DER); + if (rc < 0) + log_info ("setting CA from file '%s' failed: %s\n", + sl->d, gnutls_strerror (rc)); + } + + rc = gnutls_init (&sess->tls_session, GNUTLS_CLIENT); + if (rc < 0) + { + log_error ("gnutls_init failed: %s\n", gnutls_strerror (rc)); + err = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + rc = gnutls_priority_set_direct (sess->tls_session, + tls_priority? tls_priority : "NORMAL", + &errpos); + if (rc < 0) + { + log_error ("gnutls_priority_set_direct failed at '%s': %s\n", + errpos, gnutls_strerror (rc)); + err = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + + rc = gnutls_credentials_set (sess->tls_session, + GNUTLS_CRD_CERTIFICATE, sess->certcred); + if (rc < 0) + { + log_error ("gnutls_credentials_set failed: %s\n", gnutls_strerror (rc)); + err = gpg_error (GPG_ERR_GENERAL); + goto leave; + } + } + +#else /*!HTTP_USE_GNUTLS*/ + (void)tls_priority; +#endif /*!HTTP_USE_GNUTLS*/ + + err = 0; + +#ifdef HTTP_USE_GNUTLS + leave: +#endif /*HTTP_USE_GNUTLS*/ + if (err) + http_session_release (sess); + else + *r_session = sess; + + return err; } +/* Release a session. Take care not to release it while it is beeing + used by a http contect object. */ +void +http_session_release (http_session_t sess) +{ + if (!sess) + return; + +#ifdef HTTP_USE_GNUTLS + if (sess->tls_session) + gnutls_deinit (sess->tls_session); + if (sess->certcred) + gnutls_certificate_free_credentials (sess->certcred); + xfree (sess->servername); +#endif /*HTTP_USE_GNUTLS*/ + + xfree (sess); +} + /* Start a HTTP retrieval and return on success in R_HD a context pointer for completing the the request and to wait for the @@ -442,7 +596,7 @@ http_register_tls_callback ( gpg_error_t (*cb) (http_t, void *, int) ) gpg_error_t http_open (http_t *r_hd, http_req_t reqtype, const char *url, const char *auth, unsigned int flags, const char *proxy, - void *tls_context, const char *srvtag, strlist_t headers) + http_session_t session, const char *srvtag, strlist_t headers) { gpg_error_t err; http_t hd; @@ -458,7 +612,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url, return gpg_error_from_syserror (); hd->req_type = reqtype; hd->flags = flags; - hd->tls_context = tls_context; + hd->session = session; err = http_parse_uri (&hd->uri, url, 0); if (!err) @@ -466,7 +620,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url, if (err) { - my_socket_unref (hd->sock); + my_socket_unref (hd->sock, NULL, NULL); if (hd->fp_read) es_fclose (hd->fp_read); if (hd->fp_write) @@ -531,7 +685,7 @@ http_raw_connect (http_t *r_hd, const char *server, unsigned short port, if (!hd->fp_write) { err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ()); - my_socket_unref (cookie->sock); + my_socket_unref (cookie->sock, NULL, NULL); xfree (cookie); goto leave; } @@ -548,7 +702,7 @@ http_raw_connect (http_t *r_hd, const char *server, unsigned short port, if (!hd->fp_read) { err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ()); - my_socket_unref (cookie->sock); + my_socket_unref (cookie->sock, NULL, NULL); xfree (cookie); goto leave; } @@ -567,7 +721,7 @@ http_raw_connect (http_t *r_hd, const char *server, unsigned short port, es_fclose (hd->fp_read); if (hd->fp_write) es_fclose (hd->fp_write); - my_socket_unref (hd->sock); + my_socket_unref (hd->sock, NULL, NULL); xfree (hd); } else @@ -624,15 +778,15 @@ http_wait_response (http_t hd) if (!cookie) return gpg_err_make (default_errsource, gpg_err_code_from_syserror ()); cookie->sock = my_socket_ref (hd->sock); - if (hd->uri->use_tls) - cookie->tls_session = hd->tls_context; + cookie->session = hd->session; + cookie->use_tls = hd->uri->use_tls; hd->read_cookie = cookie; hd->fp_read = es_fopencookie (cookie, "r", cookie_functions); if (!hd->fp_read) { err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ()); - my_socket_unref (cookie->sock); + my_socket_unref (cookie->sock, NULL, NULL); xfree (cookie); hd->read_cookie = NULL; return err; @@ -654,12 +808,13 @@ http_wait_response (http_t hd) gpg_error_t http_open_document (http_t *r_hd, const char *document, const char *auth, unsigned int flags, const char *proxy, - void *tls_context, const char *srvtag, strlist_t headers) + http_session_t session, + const char *srvtag, strlist_t headers) { gpg_error_t err; err = http_open (r_hd, HTTP_REQ_GET, document, auth, flags, - proxy, tls_context, srvtag, headers); + proxy, session, srvtag, headers); if (err) return err; @@ -684,7 +839,7 @@ http_close (http_t hd, int keep_read_stream) es_onclose (hd->fp_write, 0, fp_onclose_notification, hd); /* Now we can close the streams. */ - my_socket_unref (hd->sock); + my_socket_unref (hd->sock, NULL, NULL); if (hd->fp_read && !keep_read_stream) es_fclose (hd->fp_read); if (hd->fp_write) @@ -962,16 +1117,41 @@ remove_escapes (char *string) } +/* If SPECIAL is NULL this function escapes in forms mode. */ static size_t escape_data (char *buffer, const void *data, size_t datalen, const char *special) { + int forms = !special; const unsigned char *s; size_t n = 0; + if (forms) + special = "%;?&="; + for (s = data; datalen; s++, datalen--) { - if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s)) + if (forms && *s == ' ') + { + if (buffer) + *buffer++ = '+'; + n++; + } + else if (forms && *s == '\n') + { + if (buffer) + memcpy (buffer, "%0D%0A", 6); + n += 6; + } + else if (forms && *s == '\r' && datalen > 1 && s[1] == '\n') + { + if (buffer) + memcpy (buffer, "%0D%0A", 6); + n += 6; + s++; + datalen--; + } + else if (strchr (VALID_URI_CHARS, *s) && !strchr (special, *s)) { if (buffer) *(unsigned char*)buffer++ = *s; @@ -1003,7 +1183,8 @@ insert_escapes (char *buffer, const char *string, well as escaping of characters given in SPECIALS. A common pattern for SPECIALS is "%;?&=". However it depends on the needs, for example "+" and "/: often needs to be escaped too. Returns NULL on - failure and sets ERRNO. */ + failure and sets ERRNO. If SPECIAL is NULL a dedicated forms + encoding mode is used. */ char * http_escape_string (const char *string, const char *specials) { @@ -1024,7 +1205,8 @@ http_escape_string (const char *string, const char *specials) escaping as well as escaping of characters given in SPECIALS. A common pattern for SPECIALS is "%;?&=". However it depends on the needs, for example "+" and "/: often needs to be escaped too. - Returns NULL on failure and sets ERRNO. */ + Returns NULL on failure and sets ERRNO. If SPECIAL is NULL a + dedicated forms encoding mode is used. */ char * http_escape_data (const void *data, size_t datalen, const char *specials) { @@ -1042,7 +1224,6 @@ http_escape_data (const void *data, size_t datalen, const char *specials) } - static uri_tuple_t parse_tuple (char *string) { @@ -1089,7 +1270,6 @@ static gpg_error_t send_request (http_t hd, const char *auth, const char *proxy, const char *srvtag, strlist_t headers) { - gnutls_session_t tls_session; gpg_error_t err; const char *server; char *request, *p; @@ -1100,16 +1280,44 @@ send_request (http_t hd, const char *auth, int sock; int hnf; - tls_session = hd->tls_context; - if (hd->uri->use_tls && !tls_session) + if (hd->uri->use_tls && !hd->session) { - log_error ("TLS requested but no GNUTLS context provided\n"); + log_error ("TLS requested but no session object provided\n"); return gpg_err_make (default_errsource, GPG_ERR_INTERNAL); } +#ifdef HTTP_USE_GNUTLS + if (hd->uri->use_tls && !hd->session->tls_session) + { + log_error ("TLS requested but no GNUTLS context available\n"); + return gpg_err_make (default_errsource, GPG_ERR_INTERNAL); + } +#endif /*HTTP_USE_GNUTLS*/ server = *hd->uri->host ? hd->uri->host : "localhost"; port = hd->uri->port ? hd->uri->port : 80; + /* Try to use SNI. */ +#ifdef HTTP_USE_GNUTLS + if (hd->uri->use_tls) + { + int rc; + + xfree (hd->session->servername); + hd->session->servername = xtrystrdup (server); + if (!hd->session->servername) + { + err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ()); + return err; + } + + rc = gnutls_server_name_set (hd->session->tls_session, + GNUTLS_NAME_DNS, + server, strlen (server)); + if (rc < 0) + log_info ("gnutls_server_name_set failed: %s\n", gnutls_strerror (rc)); + } +#endif /*HTTP_USE_GNUTLS*/ + if ( (proxy && *proxy) || ( (hd->flags & HTTP_FLAG_TRY_PROXY) && (http_proxy = getenv (HTTP_PROXY_ENV)) @@ -1179,11 +1387,22 @@ send_request (http_t hd, const char *auth, int rc; my_socket_ref (hd->sock); - gnutls_transport_set_ptr (tls_session, +#if GNUTLS_VERSION_NUMBER >= 0x030109 + gnutls_transport_set_int (hd->session->tls_session, hd->sock->fd); +#else + gnutls_transport_set_ptr (hd->session->tls_session, (gnutls_transport_ptr_t)(hd->sock->fd)); +#endif +#ifdef USE_NPTH + gnutls_transport_set_pull_function (hd->session->tls_session, + my_npth_read); + gnutls_transport_set_push_function (hd->session->tls_session, + my_npth_write); +#endif + do { - rc = gnutls_handshake (tls_session); + rc = gnutls_handshake (hd->session->tls_session); } while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN); if (rc < 0) @@ -1195,7 +1414,8 @@ send_request (http_t hd, const char *auth, if (tls_callback) { - err = tls_callback (hd, tls_session, 0); + hd->session->verify.done = 0; + err = tls_callback (hd, hd->session, 0); if (err) { log_info ("TLS connection authentication failed: %s\n", @@ -1227,7 +1447,7 @@ send_request (http_t hd, const char *auth, myauth = hd->uri->auth; } - authstr = make_header_line ("Authorization: Basic %s", "\r\n", + authstr = make_header_line ("Authorization: Basic ", "\r\n", myauth, strlen (myauth)); if (auth) xfree (myauth); @@ -1281,6 +1501,7 @@ send_request (http_t hd, const char *auth, return err; } + /* log_debug ("request:\n%s\nEND request\n", request); */ /* First setup estream so that we can write even the first line using estream. This is also required for the sake of gnutls. */ @@ -1295,14 +1516,14 @@ send_request (http_t hd, const char *auth, } cookie->sock = my_socket_ref (hd->sock); hd->write_cookie = cookie; - if (hd->uri->use_tls) - cookie->tls_session = tls_session; + cookie->use_tls = hd->uri->use_tls; + cookie->session = hd->session; hd->fp_write = es_fopencookie (cookie, "w", cookie_functions); if (!hd->fp_write) { err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ()); - my_socket_unref (cookie->sock); + my_socket_unref (cookie->sock, NULL, NULL); xfree (cookie); hd->write_cookie = NULL; } @@ -1491,8 +1712,8 @@ store_header (http_t hd, char *line) /* Return the header NAME from the last response. The returned value - is valid as along as HD has not been closed and no othe request has - been send. If the header was not found, NULL is returned. Name + is valid as along as HD has not been closed and no other request + has been send. If the header was not found, NULL is returned. NAME must be canonicalized, that is the first letter of each dash delimited part must be uppercase and all other letters lowercase. */ const char * @@ -1507,6 +1728,29 @@ http_get_header (http_t hd, const char *name) } +/* Return a newly allocated and NULL terminated array with pointers to + header names. The array must be released with xfree() and its + content is only values as long as no other request has been + send. */ +const char ** +http_get_header_names (http_t hd) +{ + const char **array; + size_t n; + header_t h; + + for (n=0, h = hd->headers; h; h = h->next) + n++; + array = xtrycalloc (n+1, sizeof *array); + if (array) + { + for (n=0, h = hd->headers; h; h = h->next) + array[n++] = h->name; + } + + return array; +} + /* * Parse the response from a server. @@ -1960,10 +2204,10 @@ cookie_read (void *cookie, void *buffer, size_t size) } #ifdef HTTP_USE_GNUTLS - if (c->tls_session) + if (c->use_tls && c->session && c->session->tls_session) { again: - nread = gnutls_record_recv (c->tls_session, buffer, size); + nread = gnutls_record_recv (c->session->tls_session, buffer, size); if (nread < 0) { if (nread == GNUTLS_E_INTERRUPTED) @@ -2014,18 +2258,20 @@ cookie_read (void *cookie, void *buffer, size_t size) /* Write handler for estream. */ static ssize_t -cookie_write (void *cookie, const void *buffer, size_t size) +cookie_write (void *cookie, const void *buffer_arg, size_t size) { + const char *buffer = buffer_arg; cookie_t c = cookie; int nwritten = 0; #ifdef HTTP_USE_GNUTLS - if (c->tls_session) + if (c->use_tls && c->session && c->session->tls_session) { int nleft = size; while (nleft > 0) { - nwritten = gnutls_record_send (c->tls_session, buffer, nleft); + nwritten = gnutls_record_send (c->session->tls_session, + buffer, nleft); if (nwritten <= 0) { if (nwritten == GNUTLS_E_INTERRUPTED) @@ -2063,6 +2309,18 @@ cookie_write (void *cookie, const void *buffer, size_t size) return nwritten; } + +#ifdef HTTP_USE_GNUTLS +/* Wrapper for gnutls_bye used by my_socket_unref. */ +static void +send_gnutls_bye (void *opaque) +{ + gnutls_session_t tls_session = opaque; + + gnutls_bye (tls_session, GNUTLS_SHUT_RDWR); +} +#endif /*HTTP_USE_GNUTLS*/ + /* Close handler for estream. */ static int cookie_close (void *cookie) @@ -2073,182 +2331,117 @@ cookie_close (void *cookie) return 0; #ifdef HTTP_USE_GNUTLS - if (c->tls_session && !c->keep_socket) - { - gnutls_bye (c->tls_session, GNUTLS_SHUT_RDWR); - my_socket_unref (c->sock); - } + if (c->use_tls && c->session && c->session->tls_session) + my_socket_unref (c->sock, send_gnutls_bye, c->session->tls_session); + else #endif /*HTTP_USE_GNUTLS*/ - if (c->sock && !c->keep_socket) - my_socket_unref (c->sock); + if (c->sock) + my_socket_unref (c->sock, NULL, NULL); xfree (c); return 0; } - -/**** Test code ****/ -#ifdef TEST -#ifdef HTTP_USE_GNUTLS -static gpg_error_t -verify_callback (http_t hd, void *tls_context, int reserved) + +/* Verify the credentials of the server. Returns 0 on success and + store the result in the session object. */ +gpg_error_t +http_verify_server_credentials (http_session_t sess) { - log_info ("verification of certificates skipped\n"); - return 0; -} -#endif /*HTTP_USE_GNUTLS*/ +#ifdef HTTP_USE_GNUTLS + static const char const errprefix[] = "TLS verification of peer failed"; + int rc; + unsigned int status; + const char *hostname; + const gnutls_datum_t *certlist; + unsigned int certlistlen; + gnutls_x509_crt_t cert; + sess->verify.done = 1; + sess->verify.status = 0; + sess->verify.rc = GNUTLS_E_CERTIFICATE_ERROR; -/* static void */ -/* my_gnutls_log (int level, const char *text) */ -/* { */ -/* fprintf (stderr, "gnutls:L%d: %s", level, text); */ -/* } */ + if (gnutls_certificate_type_get (sess->tls_session) != GNUTLS_CRT_X509) + { + log_error ("%s: %s\n", errprefix, "not an X.509 certificate"); + sess->verify.rc = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; + return gpg_error (GPG_ERR_GENERAL); + } -int -main (int argc, char **argv) -{ - int rc; - parsed_uri_t uri; - uri_tuple_t r; - http_t hd; - int c; - gnutls_session_t tls_session = NULL; -#ifdef HTTP_USE_GNUTLS - gnutls_certificate_credentials certcred; - const int certprio[] = { GNUTLS_CRT_X509, 0 }; -#endif /*HTTP_USE_GNUTLS*/ - header_t hdr; + rc = gnutls_certificate_verify_peers2 (sess->tls_session, &status); + if (rc) + { + log_error ("%s: %s\n", errprefix, gnutls_strerror (rc)); + return gpg_error (GPG_ERR_GENERAL); + } + if (status) + { + log_error ("%s: status=0x%04x\n", errprefix, status); + sess->verify.status = status; + return gpg_error (GPG_ERR_GENERAL); + } - es_init (); - log_set_prefix ("http-test", 1 | 4); - if (argc == 1) + hostname = sess->servername; + if (!hostname || !strchr (hostname, '.')) { - /*start_server (); */ - return 0; + log_error ("%s: %s\n", errprefix, "hostname missing"); + return gpg_error (GPG_ERR_GENERAL); } - if (argc != 2) + certlist = gnutls_certificate_get_peers (sess->tls_session, &certlistlen); + if (!certlistlen) { - fprintf (stderr, "usage: http-test uri\n"); - return 1; + log_error ("%s: %s\n", errprefix, "server did not send a certificate"); + return gpg_error (GPG_ERR_GENERAL); } - argc--; - argv++; -#ifdef HTTP_USE_GNUTLS - rc = gnutls_global_init (); - if (rc) - log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc)); - rc = gnutls_certificate_allocate_credentials (&certcred); - if (rc) - log_error ("gnutls_certificate_allocate_credentials failed: %s\n", - gnutls_strerror (rc)); -/* rc = gnutls_certificate_set_x509_trust_file */ -/* (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */ -/* if (rc) */ -/* log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */ -/* gnutls_strerror (rc)); */ - rc = gnutls_init (&tls_session, GNUTLS_CLIENT); - if (rc) - log_error ("gnutls_init failed: %s\n", gnutls_strerror (rc)); - rc = gnutls_set_default_priority (tls_session); - if (rc) - log_error ("gnutls_set_default_priority failed: %s\n", - gnutls_strerror (rc)); - rc = gnutls_certificate_type_set_priority (tls_session, certprio); - if (rc) - log_error ("gnutls_certificate_type_set_priority failed: %s\n", - gnutls_strerror (rc)); - rc = gnutls_credentials_set (tls_session, GNUTLS_CRD_CERTIFICATE, certcred); - if (rc) - log_error ("gnutls_credentials_set failed: %s\n", gnutls_strerror (rc)); -/* gnutls_global_set_log_function (my_gnutls_log); */ -/* gnutls_global_set_log_level (4); */ + /* log_debug ("Server sent %u certs\n", certlistlen); */ + /* { */ + /* int i; */ + /* char fname[50]; */ + /* FILE *fp; */ - http_register_tls_callback (verify_callback); -#endif /*HTTP_USE_GNUTLS*/ + /* for (i=0; i < certlistlen; i++) */ + /* { */ + /* snprintf (fname, sizeof fname, "xc_%d.der", i); */ + /* fp = fopen (fname, "wb"); */ + /* if (!fp) */ + /* log_fatal ("Failed to create '%s'\n", fname); */ + /* if (fwrite (certlist[i].data, certlist[i].size, 1, fp) != 1) */ + /* log_fatal ("Error writing to '%s'\n", fname); */ + /* fclose (fp); */ + /* } */ + /* } */ - rc = http_parse_uri (&uri, *argv, 1); - if (rc) + rc = gnutls_x509_crt_init (&cert); + if (rc < 0) { - log_error ("'%s': %s\n", *argv, gpg_strerror (rc)); - return 1; + return gpg_error (GPG_ERR_GENERAL); } - printf ("Scheme: %s\n", uri->scheme); - if (uri->opaque) - printf ("Value : %s\n", uri->path); - else + rc = gnutls_x509_crt_import (cert, &certlist[0], GNUTLS_X509_FMT_DER); + if (rc < 0) { - printf ("Auth : %s\n", uri->auth? uri->auth:"[none]"); - printf ("Host : %s\n", uri->host); - printf ("Port : %u\n", uri->port); - printf ("Path : %s\n", uri->path); - for (r = uri->params; r; r = r->next) - { - printf ("Params: %s", r->name); - if (!r->no_value) - { - printf ("=%s", r->value); - if (strlen (r->value) != r->valuelen) - printf (" [real length=%d]", (int) r->valuelen); - } - putchar ('\n'); - } - for (r = uri->query; r; r = r->next) - { - printf ("Query : %s", r->name); - if (!r->no_value) - { - printf ("=%s", r->value); - if (strlen (r->value) != r->valuelen) - printf (" [real length=%d]", (int) r->valuelen); - } - putchar ('\n'); - } + log_error ("%s: %s: %s\n", errprefix, "error importing certificate", + gnutls_strerror (rc)); + gnutls_x509_crt_deinit (cert); + return gpg_error (GPG_ERR_GENERAL); } - http_release_parsed_uri (uri); - uri = NULL; - rc = http_open_document (&hd, *argv, NULL, 0, NULL, tls_session, NULL, NULL); - if (rc) - { - log_error ("can't get '%s': %s\n", *argv, gpg_strerror (rc)); - return 1; - } - log_info ("open_http_document succeeded; status=%u\n", - http_get_status_code (hd)); - for (hdr = hd->headers; hdr; hdr = hdr->next) - printf ("HDR: %s: %s\n", hdr->name, hdr->value); - switch (http_get_status_code (hd)) + if (!gnutls_x509_crt_check_hostname (cert, hostname)) { - case 200: - while ((c = es_getc (http_get_read_ptr (hd))) != EOF) - putchar (c); - break; - case 301: - case 302: - printf ("Redirected to '%s'\n", http_get_header (hd, "Location")); - break; + log_error ("%s: %s\n", errprefix, "hostname does not match"); + gnutls_x509_crt_deinit (cert); + return gpg_error (GPG_ERR_GENERAL); } - http_close (hd, 0); - -#ifdef HTTP_USE_GNUTLS - gnutls_deinit (tls_session); - gnutls_certificate_free_credentials (certcred); - gnutls_global_deinit (); -#endif /*HTTP_USE_GNUTLS*/ - return 0; + gnutls_x509_crt_deinit (cert); + sess->verify.rc = 0; + return 0; /* Verification succeeded. */ +#else /*!HTTP_USE_GNUTLS*/ + (void)sess; + return gpg_error (GPG_ERR_NOT_IMPLEMENTED); +#endif } -#endif /*TEST*/ - - -/* -Local Variables: -compile-command: "gcc -I.. -I../gl -DTEST -DHAVE_CONFIG_H -Wall -O2 -g -o http-test http.c -L. -lcommon -lgcrypt -lpth -lgnutls" -End: -*/ diff --git a/common/http.h b/common/http.h index 224128b..e38fadc 100644 --- a/common/http.h +++ b/common/http.h @@ -82,10 +82,20 @@ enum HTTP_FLAG_IGNORE_IPv6 = 128 /* Do not use IPv6. */ }; + +struct http_session_s; +typedef struct http_session_s *http_session_t; + struct http_context_s; typedef struct http_context_s *http_t; -void http_register_tls_callback (gpg_error_t (*cb) (http_t, void *, int)); +void http_register_tls_callback (gpg_error_t (*cb)(http_t,http_session_t,int)); +void http_register_tls_ca (const char *fname); + +gpg_error_t http_session_new (http_session_t *r_session, + const char *tls_priority); +void http_session_release (http_session_t sess); + gpg_error_t http_parse_uri (parsed_uri_t *ret_uri, const char *uri, int no_scheme_check); @@ -101,7 +111,7 @@ gpg_error_t http_open (http_t *r_hd, http_req_t reqtype, const char *auth, unsigned int flags, const char *proxy, - void *tls_context, + http_session_t session, const char *srvtag, strlist_t headers); @@ -116,7 +126,7 @@ gpg_error_t http_open_document (http_t *r_hd, const char *auth, unsigned int flags, const char *proxy, - void *tls_context, + http_session_t session, const char *srvtag, strlist_t headers); @@ -124,6 +134,8 @@ estream_t http_get_read_ptr (http_t hd); estream_t http_get_write_ptr (http_t hd); unsigned int http_get_status_code (http_t hd); const char *http_get_header (http_t hd, const char *name); +const char **http_get_header_names (http_t hd); +gpg_error_t http_verify_server_credentials (http_session_t sess); char *http_escape_string (const char *string, const char *specials); char *http_escape_data (const void *data, size_t datalen, const char *specials); diff --git a/common/t-http.c b/common/t-http.c new file mode 100644 index 0000000..f515287 --- /dev/null +++ b/common/t-http.c @@ -0,0 +1,269 @@ +/* t-http.c + * Copyright (C) 1999, 2001, 2002, 2003, 2004, 2006, 2009, 2010, + * 2011 Free Software Foundation, Inc. + * Copyright (C) 2014 Werner Koch + * + * This file is part of GnuPG. + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of either + * + * - the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * or + * + * - the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * or both in parallel, as here. + * + * This file 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 + +#include "util.h" +#include "logging.h" +#include "http.h" + + +#ifdef HTTP_USE_GNUTLS +# include /* For init, logging, and deinit. */ +#endif /*HTTP_USE_GNUTLS*/ + + + +/* static void */ +/* read_dh_params (const char *fname) */ +/* { */ +/* gpg_error_t err; */ +/* int rc; */ +/* FILE *fp; */ +/* struct stat st; */ +/* char *buf; */ +/* size_t buflen; */ +/* gnutls_datum_t datum; */ + +/* fp = fopen (fname, "rb"); */ +/* if (!fp) */ +/* { */ +/* err = gpg_error_from_syserror (); */ +/* log_fatal ("can't open '%s': %s\n", fname, gpg_strerror (err)); */ +/* } */ + +/* if (fstat (fileno(fp), &st)) */ +/* { */ +/* err = gpg_error_from_syserror (); */ +/* log_fatal ("can't stat '%s': %s\n", fname, gpg_strerror (err)); */ +/* } */ + +/* buflen = st.st_size; */ +/* buf = xmalloc (buflen+1); */ +/* if (fread (buf, buflen, 1, fp) != 1) */ +/* { */ +/* err = gpg_error_from_syserror (); */ +/* log_fatal ("error reading '%s': %s\n", fname, gpg_strerror (err)); */ +/* } */ +/* fclose (fp); */ + +/* datum.size = buflen; */ +/* datum.data = buf; */ + +/* rc = gnutls_dh_params_import_pkcs3 (dh_params, &datum, GNUTLS_X509_FMT_PEM); */ +/* if (rc < 0) */ +/* log_fatal ("gnutls_dh_param_import failed: %s\n", gnutls_strerror (rc)); */ + +/* xfree (buf); */ +/* } */ + + + +static gpg_error_t +verify_callback (http_t hd, http_session_t session, int reserved) +{ + (void)hd; + (void)reserved; + return http_verify_server_credentials (session); +} + + +static void +my_gnutls_log (int level, const char *text) +{ + fprintf (stderr, "gnutls:L%d: %s", level, text); +} + + +/* Prepend FNAME with the srcdir environment variable's value and + return an allocated filename. */ +static char * +prepend_srcdir (const char *fname) +{ + static const char *srcdir; + char *result; + + if (!srcdir && !(srcdir = getenv ("srcdir"))) + srcdir = "."; + + result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1); + strcpy (result, srcdir); + strcat (result, "/"); + strcat (result, fname); + return result; +} + + +int +main (int argc, char **argv) +{ + gpg_error_t err; + int rc; + parsed_uri_t uri; + uri_tuple_t r; + http_t hd; + int c; + http_session_t session = NULL; + + es_init (); + log_set_prefix ("t-http", 1 | 4); + if (argc != 2) + { + fprintf (stderr, "usage: t-http uri\n"); + return 1; + } + argc--; + argv++; + +#ifdef HTTP_USE_GNUTLS + rc = gnutls_global_init (); + if (rc) + log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc)); + + http_register_tls_callback (verify_callback); + http_register_tls_ca (prepend_srcdir ("tls-ca.pem")); + + err = http_session_new (&session, NULL); + if (err) + log_error ("http_session_new failed: %s\n", gpg_strerror (err)); + + /* rc = gnutls_dh_params_init(&dh_params); */ + /* if (rc) */ + /* log_error ("gnutls_dh_params_init failed: %s\n", gnutls_strerror (rc)); */ + /* read_dh_params ("dh_param.pem"); */ + + /* rc = gnutls_certificate_set_x509_trust_file */ + /* (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */ + /* if (rc) */ + /* log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */ + /* gnutls_strerror (rc)); */ + + /* gnutls_certificate_set_dh_params (certcred, dh_params); */ + + gnutls_global_set_log_function (my_gnutls_log); + /* gnutls_global_set_log_level (2); */ + +#endif /*HTTP_USE_GNUTLS*/ + + rc = http_parse_uri (&uri, *argv, 1); + if (rc) + { + log_error ("'%s': %s\n", *argv, gpg_strerror (rc)); + return 1; + } + + printf ("Scheme: %s\n", uri->scheme); + if (uri->opaque) + printf ("Value : %s\n", uri->path); + else + { + printf ("Auth : %s\n", uri->auth? uri->auth:"[none]"); + printf ("Host : %s\n", uri->host); + printf ("Port : %u\n", uri->port); + printf ("Path : %s\n", uri->path); + for (r = uri->params; r; r = r->next) + { + printf ("Params: %s", r->name); + if (!r->no_value) + { + printf ("=%s", r->value); + if (strlen (r->value) != r->valuelen) + printf (" [real length=%d]", (int) r->valuelen); + } + putchar ('\n'); + } + for (r = uri->query; r; r = r->next) + { + printf ("Query : %s", r->name); + if (!r->no_value) + { + printf ("=%s", r->value); + if (strlen (r->value) != r->valuelen) + printf (" [real length=%d]", (int) r->valuelen); + } + putchar ('\n'); + } + } + http_release_parsed_uri (uri); + uri = NULL; + + rc = http_open_document (&hd, *argv, NULL, 0, NULL, session, NULL, NULL); + if (rc) + { + log_error ("can't get '%s': %s\n", *argv, gpg_strerror (rc)); + return 1; + } + log_info ("open_http_document succeeded; status=%u\n", + http_get_status_code (hd)); + + { + const char **names; + int i; + + names = http_get_header_names (hd); + if (!names) + log_fatal ("http_get_header_names failed: %s\n", + gpg_strerror (gpg_error_from_syserror ())); + for (i = 0; names[i]; i++) + printf ("HDR: %s: %s\n", names[i], http_get_header (hd, names[i])); + xfree (names); + } + + switch (http_get_status_code (hd)) + { + case 200: + case 400: + case 401: + case 403: + case 404: + while ((c = es_getc (http_get_read_ptr (hd))) != EOF) + putchar (c); + break; + case 301: + case 302: + printf ("Redirected to '%s'\n", http_get_header (hd, "Location")); + break; + } + http_close (hd, 0); + + http_session_release (session); +#ifdef HTTP_USE_GNUTLS + gnutls_global_deinit (); +#endif /*HTTP_USE_GNUTLS*/ + + return 0; +} diff --git a/common/tls-ca.pem b/common/tls-ca.pem new file mode 100644 index 0000000..c296466 --- /dev/null +++ b/common/tls-ca.pem @@ -0,0 +1,30 @@ +Issuer ...: /CN=UTN-USERFirst-Hardware/OU=http:\x2f\x2fwww.usertrust.com/O=The USERTRUST Network/L=Salt Lake City/ST=UT/C=US +Serial ...: 44BE0C8B500024B411D3362AFE650AFD +Subject ..: /CN=UTN-USERFirst-Hardware/OU=http:\x2f\x2fwww.usertrust.com/O=The USERTRUST Network/L=Salt Lake City/ST=UT/C=US + +-----BEGIN CERTIFICATE----- +MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB +lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug +Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho +dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt +SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG +A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe +MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v +d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh +cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn +0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ +M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a +MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd +oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI +DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy +oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 +dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy +bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF +BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM +//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli +CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE +CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t +3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS +KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== +-----END CERTIFICATE----- diff --git a/configure.ac b/configure.ac index 19c9816..21f5fb6 100644 --- a/configure.ac +++ b/configure.ac @@ -58,6 +58,8 @@ NEED_KSBA_VERSION=1.2.0 NEED_NPTH_API=1 NEED_NPTH_VERSION=0.91 +NEED_GNUTLS_VERSION=3.0 + development_version=mym4_isgit PACKAGE=$PACKAGE_NAME @@ -912,6 +914,26 @@ else ***]]) fi +# +# Check whether GNUTLS is available +# +PKG_CHECK_MODULES([LIBGNUTLS], [gnutls >= $NEED_GNUTLS_VERSION], + [have_gnutls=yes], + [have_gnutls=no]) +if test "$have_gnutls" = "yes"; then + AC_SUBST([LIBGNUTLS_CFLAGS]) + AC_SUBST([LIBGNUTLS_LIBS]) + AC_DEFINE(HTTP_USE_GNUTLS, 1, [Enable GNUTLS support in http.c]) +else + tmp=$(echo "$LIBGNUTLS_PKG_ERRORS" | tr '\n' '\v' | sed 's/\v/\n*** /g') + AC_MSG_WARN([[ +*** +*** Building without GNUTLS - no TLS access to keyservers. +*** +*** $tmp]]) +fi + + AC_MSG_NOTICE([checking for networking options]) @@ -1867,6 +1889,8 @@ echo " Use standard socket: $use_standard_socket Dirmngr auto start: $dirmngr_auto_start Readline support: $gnupg_cv_have_readline + DNS SRV support: $use_dns_srv + TLS support: $have_gnutls " if test x"$use_regex" != xyes ; then echo " diff --git a/dirmngr/Makefile.am b/dirmngr/Makefile.am index 7c43165..b5bef45 100644 --- a/dirmngr/Makefile.am +++ b/dirmngr/Makefile.am @@ -60,8 +60,10 @@ dirmngr_SOURCES += ldap-wrapper-ce.c dirmngr_ldap.c endif -dirmngr_LDADD = $(libcommonpth) ../gl/libgnu.a $(DNSLIBS) $(LIBASSUAN_LIBS) \ - $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(NPTH_LIBS) $(LIBINTL) $(LIBICONV) +dirmngr_LDADD = $(libcommontlsnpth) $(libcommonpth) \ + ../gl/libgnu.a $(DNSLIBS) $(LIBASSUAN_LIBS) \ + $(LIBGCRYPT_LIBS) $(KSBA_LIBS) $(NPTH_LIBS) \ + $(LIBGNUTLS_LIBS) $(LIBINTL) $(LIBICONV) if !USE_LDAPWRAPPER dirmngr_LDADD += $(LDAPLIBS) endif @@ -79,8 +81,7 @@ endif dirmngr_client_SOURCES = dirmngr-client.c dirmngr_client_LDADD = $(libcommon) no-libgcrypt.o \ ../gl/libgnu.a $(LIBASSUAN_LIBS) \ - $(GPG_ERROR_LIBS) $(LIBINTL) \ - $(LIBICONV) + $(GPG_ERROR_LIBS) $(NETLIBS) $(LIBINTL) $(LIBICONV) dirmngr_client_LDFLAGS = $(extra_bin_ldflags) commit 84289e85c72ae58c321dfdb96816700a6b7f7122 Author: Werner Koch Date: Fri May 2 08:06:10 2014 +0200 common: Cleanup the use of USE_NPTH and HAVE_NPTH macros. * configure.ac (HAVE_NPTH): New ac_define. * common/estream.c: Use USE_NPTH instead of HAVE_NPTH. * common/http.c: Ditto. Replace remaining calls to pth by npth calls. (connect_server): Remove useless _(). * common/exechelp-posix.c, common/exechelp-w32.c * common/exechelp-w32ce.c: Use HAVE_PTH to include npth.h. * common/init.c (_init_common_subsystems): Remove call to pth_init. * common/sysutils.c (gnupg_sleep): Use npth_sleep. * scd/ccid-driver.c (my_sleep): Ditto. -- USE_NPTH is used in case were we may build with and without nPth. The missing definition HAVE_NPTH didn't allowed us to build outher sources with nPTh support. diff --git a/common/estream.c b/common/estream.c index 34726a3..3f924ab 100644 --- a/common/estream.c +++ b/common/estream.c @@ -162,7 +162,7 @@ typedef void (*func_free_t) (void *mem); /* Primitive system I/O. */ -#ifdef HAVE_NPTH +#ifdef USE_NPTH # define ESTREAM_SYS_READ do_npth_read # define ESTREAM_SYS_WRITE do_npth_write # define ESTREAM_SYS_YIELD() npth_usleep (0) @@ -197,7 +197,7 @@ struct estream_internal unsigned char buffer[BUFFER_BLOCK_SIZE]; unsigned char unread_buffer[BUFFER_UNREAD_SIZE]; -#ifdef HAVE_NPTH +#ifdef USE_NPTH npth_mutex_t lock; /* Lock. */ #endif @@ -242,7 +242,7 @@ static int custom_std_fds[3]; static unsigned char custom_std_fds_valid[3]; /* A lock object for the estream list and the custom_std_fds array. */ -#ifdef HAVE_NPTH +#ifdef USE_NPTH static npth_mutex_t estream_list_lock; #endif @@ -358,7 +358,7 @@ map_w32_to_errno (DWORD w32_err) static int init_stream_lock (estream_t ES__RESTRICT stream) { -#ifdef HAVE_NPTH +#ifdef USE_NPTH int rc; if (!stream->intern->samethread) @@ -380,7 +380,7 @@ init_stream_lock (estream_t ES__RESTRICT stream) static void lock_stream (estream_t ES__RESTRICT stream) { -#ifdef HAVE_NPTH +#ifdef USE_NPTH if (!stream->intern->samethread) { dbg_lock_1 ("enter lock_stream for %p\n", stream); @@ -396,7 +396,7 @@ lock_stream (estream_t ES__RESTRICT stream) static int trylock_stream (estream_t ES__RESTRICT stream) { -#ifdef HAVE_NPTH +#ifdef USE_NPTH int rc; if (!stream->intern->samethread) @@ -418,7 +418,7 @@ trylock_stream (estream_t ES__RESTRICT stream) static void unlock_stream (estream_t ES__RESTRICT stream) { -#ifdef HAVE_NPTH +#ifdef USE_NPTH if (!stream->intern->samethread) { dbg_lock_1 ("enter unlock_stream for %p\n", stream); @@ -434,7 +434,7 @@ unlock_stream (estream_t ES__RESTRICT stream) static int init_list_lock (void) { -#ifdef HAVE_NPTH +#ifdef USE_NPTH int rc; dbg_lock_0 ("enter init_list_lock\n"); @@ -450,7 +450,7 @@ init_list_lock (void) static void lock_list (void) { -#ifdef HAVE_NPTH +#ifdef USE_NPTH dbg_lock_0 ("enter lock_list\n"); npth_mutex_lock (&estream_list_lock); dbg_lock_0 ("leave lock_list\n"); @@ -461,7 +461,7 @@ lock_list (void) static void unlock_list (void) { -#ifdef HAVE_NPTH +#ifdef USE_NPTH dbg_lock_0 ("enter unlock_list\n"); npth_mutex_unlock (&estream_list_lock); dbg_lock_0 ("leave unlock_list\n"); @@ -548,7 +548,7 @@ do_list_remove (estream_t stream, int with_locked_list) * write, assuming that we do I/O on a plain file where the operation * can't block. FIXME: Is this still needed for npth? */ -#ifdef HAVE_NPTH +#ifdef USE_NPTH static int do_npth_read (int fd, void *buffer, size_t size) { @@ -574,7 +574,7 @@ do_npth_write (int fd, const void *buffer, size_t size) return npth_write (fd, buffer, size); # endif /* !HAVE_W32_SYSTEM*/ } -#endif /*HAVE_NPTH*/ +#endif /*USE_NPTH*/ @@ -1125,7 +1125,7 @@ es_func_w32_read (void *cookie, void *buffer, size_t size) { do { -#ifdef HAVE_NPTH +#ifdef USE_NPTH /* Note: Our pth_read actually uses HANDLE! FIXME: Check whether this is the case for npth. */ bytes_read = npth_read ((int)w32_cookie->hd, buffer, size); @@ -1171,7 +1171,7 @@ es_func_w32_write (void *cookie, const void *buffer, size_t size) { do { -#ifdef HAVE_NPTH +#ifdef USE_NPTH /* Note: Our pth_write actually uses HANDLE! */ bytes_written = npth_write ((int)w32_cookie->hd, buffer, size); #else diff --git a/common/exechelp-posix.c b/common/exechelp-posix.c index 1290cfd..249d38d 100644 --- a/common/exechelp-posix.c +++ b/common/exechelp-posix.c @@ -50,7 +50,7 @@ #undef USE_NPTH #endif -#ifdef USE_NPTH +#ifdef HAVE_NPTH #include #endif #include diff --git a/common/exechelp-w32.c b/common/exechelp-w32.c index 61193ed..7bcd79b 100644 --- a/common/exechelp-w32.c +++ b/common/exechelp-w32.c @@ -50,7 +50,7 @@ #undef USE_NPTH #endif -#ifdef USE_NPTH +#ifdef HAVE_NPTH #include #endif diff --git a/common/exechelp-w32ce.c b/common/exechelp-w32ce.c index 886d517..cca55c8 100644 --- a/common/exechelp-w32ce.c +++ b/common/exechelp-w32ce.c @@ -50,7 +50,7 @@ #undef USE_NPTH #endif -#ifdef USE_NPTH +#ifdef HAVE_NPTH #include #endif diff --git a/common/http.c b/common/http.c index 5410141..11a7130 100644 --- a/common/http.c +++ b/common/http.c @@ -74,15 +74,13 @@ #endif /*!HAVE_W32_SYSTEM*/ #ifdef WITHOUT_NPTH /* Give the Makefile a chance to build without Pth. */ -# undef HAVE_NPTH # undef USE_NPTH #endif -#ifdef HAVE_NPTH +#ifdef USE_NPTH # include #endif - #ifdef HTTP_USE_GNUTLS # include /* For non-understandable reasons GNUTLS dropped the _t suffix from @@ -94,7 +92,7 @@ typedef gnutls_transport_ptr gnutls_transport_ptr_t; #endif /*HTTP_USE_GNUTLS*/ #ifdef TEST -#undef USE_DNS_SRV +# undef USE_DNS_SRV #endif #include "util.h" @@ -119,10 +117,10 @@ struct srventry #endif/*!USE_DNS_SRV*/ -#ifdef HAVE_NPTH -# 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)) +#ifdef USE_NPTH +# define my_select(a,b,c,d,e) npth_select ((a), (b), (c), (d), (e)) +# define my_connect(a,b,c) npth_connect ((a), (b), (c)) +# define my_accept(a,b,c) npth_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)) @@ -359,8 +357,9 @@ my_socket_unref (my_socket_t so) /* #define my_socket_unref(a) _my_socket_unref ((a),__LINE__) */ + /* This notification function is called by estream whenever stream is - closed. Its purpose is to mark the the closing in the handle so + closed. Its purpose is to mark the closing in the handle so that a http_close won't accidentally close the estream. The function http_close removes this notification so that it won't be called if http_close was used before an es_fclose. */ @@ -1835,7 +1834,7 @@ connect_server (const char *server, unsigned short port, sock = socket (host->h_addrtype, SOCK_STREAM, 0); if (sock == -1) { - log_error (_("error creating socket: %s\n"), strerror (errno)); + log_error ("error creating socket: %s\n", strerror (errno)); xfree (serverlist); return -1; } @@ -1879,7 +1878,7 @@ connect_server (const char *server, unsigned short port, #ifdef HAVE_W32_SYSTEM log_error ("can't connect to '%s': %s%sec=%d\n", server, - hostfound? "":_("host not found"), + hostfound? "":"host not found", hostfound? "":" - ", (int)WSAGetLastError()); #else log_error ("can't connect to '%s': %s\n", @@ -1906,16 +1905,16 @@ write_server (int sock, const char *data, size_t length) nleft = length; while (nleft > 0) { -#if defined(HAVE_W32_SYSTEM) && !defined(HAVE_NPTH) +#if defined(HAVE_W32_SYSTEM) && !defined(USE_NPTH) nwritten = send (sock, data, nleft, 0); if ( nwritten == SOCKET_ERROR ) { log_info ("network write failed: ec=%d\n", (int)WSAGetLastError ()); return gpg_error (GPG_ERR_NETWORK); } -#else /*!HAVE_W32_SYSTEM || HAVE_NPTH*/ -# ifdef HAVE_NPTH - nwritten = pth_write (sock, data, nleft); +#else /*!HAVE_W32_SYSTEM || USE_NPTH*/ +# ifdef USE_NPTH + nwritten = npth_write (sock, data, nleft); # else nwritten = write (sock, data, nleft); # endif @@ -1935,7 +1934,7 @@ write_server (int sock, const char *data, size_t length) log_info ("network write failed: %s\n", strerror (errno)); return gpg_error_from_syserror (); } -#endif /*!HAVE_W32_SYSTEM || HAVE_NPTH*/ +#endif /*!HAVE_W32_SYSTEM || USE_NPTH*/ nleft -= nwritten; data += nwritten; } @@ -1990,8 +1989,8 @@ cookie_read (void *cookie, void *buffer, size_t size) { do { -#ifdef HAVE_NPTH - nread = pth_read (c->sock->fd, buffer, size); +#ifdef USE_NPTH + nread = npth_read (c->sock->fd, buffer, size); #elif defined(HAVE_W32_SYSTEM) /* Under Windows we need to use recv for a socket. */ nread = recv (c->sock->fd, buffer, size, 0); diff --git a/common/init.c b/common/init.c index 35e623f..91ee912 100644 --- a/common/init.c +++ b/common/init.c @@ -156,18 +156,12 @@ _init_common_subsystems (gpg_err_source_t errsource, int *argcp, char ***argvp) #ifdef HAVE_W32_SYSTEM /* For W32 we need to initialize the socket layer. This is because we use recv and send in libassuan as well as at some other - places. If we are building with PTH we let pth_init do it. We - can't do much on error so we ignore them. An error would anyway - later pop up if one of the socket functions is used. */ -# ifdef HAVE_NPTH - pth_init (); -# else + places. */ { WSADATA wsadat; WSAStartup (0x202, &wsadat); } -# endif /*!HAVE_NPTH*/ #endif #ifdef HAVE_W32CE_SYSTEM diff --git a/common/sysutils.c b/common/sysutils.c index 95e0f8c..afb12ed 100644 --- a/common/sysutils.c +++ b/common/sysutils.c @@ -275,18 +275,8 @@ check_permissions(const char *path,int extension,int checkonly) void gnupg_sleep (unsigned int seconds) { -#ifdef HAVE_NPTH - /* With Pth we force a regular sleep for seconds == 0 so that also - the process will give up its timeslot. */ - if (!seconds) - { -# ifdef HAVE_W32_SYSTEM - Sleep (0); -# else - sleep (0); -# endif - } - pth_sleep (seconds); +#ifdef USE_NPTH + npth_sleep (seconds); #else /* Fixme: make sure that a sleep won't wake up to early. */ # ifdef HAVE_W32_SYSTEM diff --git a/configure.ac b/configure.ac index 096e3e1..19c9816 100644 --- a/configure.ac +++ b/configure.ac @@ -900,9 +900,10 @@ AC_DEFINE_UNQUOTED(SHRED, # AM_PATH_NPTH("$NEED_NPTH_API:$NEED_NPTH_VERSION",have_npth=yes,have_npth=no) if test "$have_npth" = "yes"; then - # We define this macro because some code parts require it. - AC_DEFINE(USE_NPTH, 1, + AC_DEFINE(HAVE_NPTH, 1, [Defined if the New Portable Thread Library is available]) + AC_DEFINE(USE_NPTH, 1, + [Defined if support for nPth is requested and nPth is available]) else AC_MSG_WARN([[ *** diff --git a/scd/ccid-driver.c b/scd/ccid-driver.c index 0ac5aaf..60ac576 100644 --- a/scd/ccid-driver.c +++ b/scd/ccid-driver.c @@ -315,18 +315,8 @@ set_msg_len (unsigned char *msg, unsigned int length) static void my_sleep (int seconds) { -#ifdef HAVE_NPTH - /* With Pth we also call the standard sleep(0) so that the process - may give up its timeslot. */ - if (!seconds) - { -# ifdef HAVE_W32_SYSTEM - Sleep (0); -# else - sleep (0); -# endif - } - pth_sleep (seconds); +#ifdef USE_NPTH + npth_sleep (seconds); #else # ifdef HAVE_W32_SYSTEM Sleep (seconds*1000); ----------------------------------------------------------------------- Summary of changes: am/cmacros.am | 2 + common/Makefile.am | 28 ++- common/estream.c | 28 +-- common/exechelp-posix.c | 2 +- common/exechelp-w32.c | 2 +- common/exechelp-w32ce.c | 2 +- common/http.c | 642 ++++++++++++++++++++++++++++++----------------- common/http.h | 18 +- common/init.c | 8 +- common/sysutils.c | 14 +- common/t-http.c | 269 ++++++++++++++++++++ common/t-openpgp-oid.c | 7 +- common/tls-ca.pem | 30 +++ configure.ac | 29 ++- dirmngr/Makefile.am | 9 +- scd/ccid-driver.c | 14 +- 16 files changed, 816 insertions(+), 288 deletions(-) create mode 100644 common/t-http.c create mode 100644 common/tls-ca.pem hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Mon May 5 16:22:40 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 05 May 2014 16:22:40 +0200 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-405-g60e2fc7 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 60e2fc7d38d8b37d1de944cf230e410c2ce37d5e (commit) via ea0f5481f01eacedff264bf08144164aa989ec4d (commit) via 0e59195642eb26263b8e0b9200290538631d35cd (commit) from 2def230231abd34f6012df284ab468321ffedc10 (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 60e2fc7d38d8b37d1de944cf230e410c2ce37d5e Author: Werner Koch Date: Mon May 5 16:09:45 2014 +0200 dirmngr: Add support for hkps keyservers. * dirmngr/dirmngr.c: Include gnutls.h. (opts): Add --gnutls-debug and --hkp-cacert. (opt_gnutls_debug, my_gnutls_log): New. (set_debug): Set gnutls log level. (parse_rereadable_options): Register a CA file. (main): Init GNUTLS. * dirmngr/ks-engine-hkp.c (ks_hkp_help): Support hkps. (send_request): Ditto. diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c index 81da029..8f85e48 100644 --- a/dirmngr/dirmngr.c +++ b/dirmngr/dirmngr.c @@ -40,6 +40,9 @@ # include #endif #include +#ifdef HTTP_USE_GNUTLS +# include +#endif /*HTTP_USE_GNUTLS*/ #define JNLIB_NEED_LOG_LOGV @@ -92,6 +95,7 @@ enum cmd_and_opt_values { oDebugAll, oDebugWait, oDebugLevel, + oGnutlsDebug, oNoGreeting, oNoOptions, oHomedir, @@ -116,6 +120,7 @@ enum cmd_and_opt_values { oOCSPMaxPeriod, oOCSPCurrentPeriod, oMaxReplies, + oHkpCaCert, oFakedSystemTime, oForce, oAllowOCSP, @@ -195,11 +200,16 @@ static ARGPARSE_OPTS opts[] = { ARGPARSE_s_i (oMaxReplies, "max-replies", N_("|N|do not return more than N items in one query")), + ARGPARSE_s_s (oHkpCaCert, "hkp-cacert", + N_("|FILE|use the CA certifciates in FILE for HKP over TLS")), + + ARGPARSE_s_s (oSocketName, "socket-name", "@"), /* Only for debugging. */ ARGPARSE_s_u (oFakedSystemTime, "faked-system-time", "@"), /*(epoch time)*/ ARGPARSE_p_u (oDebug, "debug", "@"), ARGPARSE_s_n (oDebugAll, "debug-all", "@"), + ARGPARSE_s_i (oGnutlsDebug, "gnutls-debug", "@"), ARGPARSE_s_i (oDebugWait, "debug-wait", "@"), ARGPARSE_s_n (oNoGreeting, "no-greeting", "@"), ARGPARSE_s_s (oHomedir, "homedir", "@"), @@ -234,6 +244,9 @@ static char *current_logfile; /* Helper to implement --debug-level. */ static const char *debug_level; +/* Helper to set the GNUTLS log level. */ +static int opt_gnutls_debug = -1; + /* Flag indicating that a shutdown has been requested. */ static volatile int shutdown_pending; @@ -331,6 +344,20 @@ my_ksba_hash_buffer (void *arg, const char *oid, } +/* GNUTLS log function callback. */ +static void +my_gnutls_log (int level, const char *text) +{ + int n; + + n = strlen (text); + while (n && text[n-1] == '\n') + n--; + + log_debug ("gnutls:L%d: %.*s\n", level, n, text); +} + + /* Setup the debugging. With a LEVEL of NULL only the active debug flags are propagated to the subsystems. With LEVEL set, a specific set of debug flags is set; thus overriding all flags already @@ -382,6 +409,14 @@ set_debug (void) if (opt.debug & DBG_CRYPTO_VALUE ) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1); + +#ifdef HTTP_USE_GNUTLS + if (opt_gnutls_debug >= 0) + { + gnutls_global_set_log_function (my_gnutls_log); + gnutls_global_set_log_level (opt_gnutls_debug); + } +#endif /*HTTP_USE_GNUTLS*/ } @@ -439,6 +474,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) opt.ocsp_signer = tmp; } FREE_STRLIST (opt.ignored_cert_extensions); + http_register_tls_ca (NULL); return 1; } @@ -449,6 +485,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) case oDebug: opt.debug |= pargs->r.ret_ulong; break; case oDebugAll: opt.debug = ~0; break; case oDebugLevel: debug_level = pargs->r.ret_str; break; + case oGnutlsDebug: opt_gnutls_debug = pargs->r.ret_int; break; case oLogFile: if (!reread) @@ -490,6 +527,10 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread) case oMaxReplies: opt.max_replies = pargs->r.ret_int; break; + case oHkpCaCert: + http_register_tls_ca (pargs->r.ret_str); + break; + case oIgnoreCertExtension: add_to_strlist (&opt.ignored_cert_extensions, pargs->r.ret_str); break; @@ -628,6 +669,12 @@ main (int argc, char **argv) ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free ); ksba_set_hash_buffer_function (my_ksba_hash_buffer, NULL); + /* Init GNUTLS. */ +#ifdef HTTP_USE_GNUTLS + rc = gnutls_global_init (); + if (rc) + log_fatal ("gnutls_global_init failed: %s\n", gnutls_strerror (rc)); +#endif /*HTTP_USE_GNUTLS*/ /* Init Assuan. */ malloc_hooks.malloc = gcry_malloc; diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c index fa616a0..c115cf5 100644 --- a/dirmngr/ks-engine-hkp.c +++ b/dirmngr/ks-engine-hkp.c @@ -628,12 +628,14 @@ ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri) const char const data[] = "Handler for HKP URLs:\n" " hkp://\n" + " hkps://\n" "Supported methods: search, get, put\n"; gpg_error_t err; if (!uri) - err = ks_print_help (ctrl, " hkp"); - else if (uri->is_http && !strcmp (uri->scheme, "hkp")) + err = ks_print_help (ctrl, " hkp\n hkps"); + else if (uri->is_http && (!strcmp (uri->scheme, "hkp") + || !strcmp (uri->scheme, "hkps"))) err = ks_print_help (ctrl, data); else err = 0; @@ -747,6 +749,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr, estream_t *r_fp) { gpg_error_t err; + http_session_t session = NULL; http_t http = NULL; int redirects_left = MAX_REDIRECTS; estream_t fp = NULL; @@ -754,6 +757,10 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr, *r_fp = NULL; + err = http_session_new (&session, NULL); + if (err) + goto leave; + once_more: err = http_open (&http, post_cb? HTTP_REQ_POST : HTTP_REQ_GET, @@ -761,7 +768,8 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr, /* fixme: AUTH */ NULL, httpflags, /* fixme: proxy*/ NULL, - NULL, NULL, + session, + NULL, /*FIXME curl->srvtag*/NULL); if (!err) { @@ -798,6 +806,13 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr, goto leave; } + if (http_get_tls_info (http, NULL)) + { + /* Update the httpflags so that a redirect won't fallback to an + unencrypted connection. */ + httpflags |= HTTP_FLAG_FORCE_TLS; + } + switch (http_get_status_code (http)) { case 200: @@ -806,6 +821,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr, case 301: case 302: + case 307: { const char *s = http_get_header (http, "Location"); @@ -837,6 +853,10 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr, goto leave; } + /* FIXME: We should register a permanent redirection and whether a + host has ever used TLS so that future calls will always use + TLS. */ + fp = http_get_read_ptr (http); if (!fp) { @@ -851,6 +871,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr, leave: http_close (http, 0); + http_session_release (session); xfree (request_buffer); return err; } diff --git a/dirmngr/sks-keyservers.netCA.pem b/dirmngr/sks-keyservers.netCA.pem new file mode 100644 index 0000000..24a2ad2 --- /dev/null +++ b/dirmngr/sks-keyservers.netCA.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFizCCA3OgAwIBAgIJAK9zyLTPn4CPMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNV +BAYTAk5PMQ0wCwYDVQQIDARPc2xvMR4wHAYDVQQKDBVza3Mta2V5c2VydmVycy5u +ZXQgQ0ExHjAcBgNVBAMMFXNrcy1rZXlzZXJ2ZXJzLm5ldCBDQTAeFw0xMjEwMDkw +MDMzMzdaFw0yMjEwMDcwMDMzMzdaMFwxCzAJBgNVBAYTAk5PMQ0wCwYDVQQIDARP +c2xvMR4wHAYDVQQKDBVza3Mta2V5c2VydmVycy5uZXQgQ0ExHjAcBgNVBAMMFXNr +cy1rZXlzZXJ2ZXJzLm5ldCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBANdsWy4PXWNUCkS3L//nrd0GqN3dVwoBGZ6w94Tw2jPDPifegwxQozFXkG6I +6A4TK1CJLXPvfz0UP0aBYyPmTNadDinaB9T4jIwd4rnxl+59GiEmqkN3IfPsv5Jj +MkKUmJnvOT0DEVlEaO1UZIwx5WpfprB3mR81/qm4XkAgmYrmgnLXd/pJDAMk7y1F +45b5zWofiD5l677lplcIPRbFhpJ6kDTODXh/XEdtF71EAeaOdEGOvyGDmCO0GWqS +FDkMMPTlieLA/0rgFTcz4xwUYj/cD5e0ZBuSkYsYFAU3hd1cGfBue0cPZaQH2HYx +Qk4zXD8S3F4690fRhr+tki5gyG6JDR67aKp3BIGLqm7f45WkX1hYp+YXywmEziM4 +aSbGYhx8hoFGfq9UcfPEvp2aoc8u5sdqjDslhyUzM1v3m3ZGbhwEOnVjljY6JJLx +MxagxnZZSAY424ZZ3t71E/Mn27dm2w+xFRuoy8JEjv1d+BT3eChM5KaNwrj0IO/y +u8kFIgWYA1vZ/15qMT+tyJTfyrNVV/7Df7TNeWyNqjJ5rBmt0M6NpHG7CrUSkBy9 +p8JhimgjP5r0FlEkgg+lyD+V79H98gQfVgP3pbJICz0SpBQf2F/2tyS4rLm+49rP +fcOajiXEuyhpcmzgusAj/1FjrtlynH1r9mnNaX4e+rLWzvU5AgMBAAGjUDBOMB0G +A1UdDgQWBBTkwyoJFGfYTVISTpM8E+igjdq28zAfBgNVHSMEGDAWgBTkwyoJFGfY +TVISTpM8E+igjdq28zAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQAR +OXnYwu3g1ZjHyley3fZI5aLPsaE17cOImVTehC8DcIphm2HOMR/hYTTL+V0G4P+u +gH+6xeRLKSHMHZTtSBIa6GDL03434y9CBuwGvAFCMU2GV8w92/Z7apkAhdLToZA/ +X/iWP2jeaVJhxgEcH8uPrnSlqoPBcKC9PrgUzQYfSZJkLmB+3jEa3HKruy1abJP5 +gAdQvwvcPpvYRnIzUc9fZODsVmlHVFBCl2dlu/iHh2h4GmL4Da2rRkUMlbVTdioB +UYIvMycdOkpH5wJftzw7cpjsudGas0PARDXCFfGyKhwBRFY7Xp7lbjtU5Rz0Gc04 +lPrhDf0pFE98Aw4jJRpFeWMjpXUEaG1cq7D641RpgcMfPFvOHY47rvDTS7XJOaUT +BwRjmDt896s6vMDcaG/uXJbQjuzmmx3W2Idyh3s5SI0GTHb0IwMKYb4eBUIpQOnB +cE77VnCYqKvN1NVYAqhWjXbY7XasZvszCRcOG+W3FqNaHOK/n/0ueb0uijdLan+U +f4p1bjbAox8eAOQS/8a3bzkJzdyBNUKGx1BIK2IBL9bn/HravSDOiNRSnZ/R3l9G +ZauX0tu7IIDlRCILXSyeazu0aj/vdT3YFQXPcvt5Fkf5wiNTo53f72/jYEJd6qph +WrpoKqrwGwTpRUCMhYIUt65hsTxCiJJ5nKe39h46sg== +-----END CERTIFICATE----- diff --git a/doc/dirmngr.texi b/doc/dirmngr.texi index e626487..7b2f92c 100644 --- a/doc/dirmngr.texi +++ b/doc/dirmngr.texi @@ -18,7 +18,7 @@ @mansect synopsis @ifset manverb .B dirmngr -.RI [ options ] +.RI [ options ] .I command .RI [ args ] @end ifset @@ -32,7 +32,7 @@ system daemon through the @command{dirmngr-client} tool. If @command{dirmngr} is started in system daemon mode, it uses a directory layout as common for system daemons and does not make use of -the default @file{~/.gnupg} directory. +the default @file{~/.gnupg} directory. @manpause @@ -175,7 +175,7 @@ numeric value or by a keyword: @item none No debugging at all. A value of less than 1 may be used instead of the keyword. - at item basic + at item basic Some basic debug messages. A value between 1 and 2 may be used instead of the keyword. @item advanced @@ -204,6 +204,10 @@ usual C-Syntax. @opindex debug-all Same as @code{--debug=0xffffffff} + at item --gnutls-debug @var{level} + at opindex gnutls-debug +Enable debugging of GNUTLS at @var{level}. + @item --debug-wait @var{n} @opindex debug-wait When running in server mode, wait @var{n} seconds before entering the @@ -247,12 +251,12 @@ scheme are ignored when looking for a suitable DP. @item --ignore-ldap-dp @opindex ignore-ldap-dp This is similar to @option{--ignore-http-dp} but ignores entries using -the @acronym{LDAP} scheme. Both options may be combined resulting in +the @acronym{LDAP} scheme. Both options may be combined resulting in ignoring DPs entirely. @item --ignore-ocsp-service-url @opindex ignore-ocsp-service-url -Ignore all OCSP URLs contained in the certificate. The effect is to +Ignore all OCSP URLs contained in the certificate. The effect is to force the use of the default responder. @item --honor-http-proxy @@ -284,7 +288,7 @@ configured LDAP server if the connection using the "proxy" failed. @item --ldapserverlist-file @var{file} @opindex ldapserverlist-file Read the list of LDAP servers to consult for CRLs and certificates from -file instead of the default per-user ldap server list file. The default +file instead of the default per-user ldap server list file. The default value for @var{file} is @file{dirmngr_ldapservers.conf} or @file{ldapservers.conf} when running in @option{--daemon} mode. @@ -328,7 +332,7 @@ Note: The current version of dirmngr has this option disabled by default. @item --allow-ocsp @opindex allow-ocsp -This option enables OCSP support if requested by the client. +This option enables OCSP support if requested by the client. OCSP requests are rejected by default because they may violate the privacy of the user; for example it is possible to track the time when @@ -395,10 +399,17 @@ won't be rejected due to an unknown critical extension. Use this option with care because extensions are usually flagged as critical for a reason. + at item --hkp-cacert @var{file} +Use the root certificates in @var{file} for verification of the TLS +certificates used with @code{hkps} (keyserver access over TLS). If +the file is in PEM format a suffix of @code{.pem} is expected for + at var{file}. This option may be given multiple times to add more +root certificates. + @end table - at c + at c @c Dirmngr Configuration @c @mansect files @@ -472,7 +483,7 @@ Please ignore the output; it is not needed anymore. Check the log file to see whether all trusted root certificates have been loaded correctly. - at c + at c @c Dirmngr Signals @c @mansect signals @@ -480,7 +491,7 @@ to see whether all trusted root certificates have been loaded correctly. @section Use of signals. A running @command{dirmngr} may be controlled by signals, i.e. using -the @command{kill} command to send a signal to the process. +the @command{kill} command to send a signal to the process. Here is a list of supported signals: @@ -522,7 +533,7 @@ This prints some caching statistics to the log file. Dirmngr is supposed to be used as a system wide daemon, it should be started like: - at example + at example dirmngr --daemon @end example @@ -613,7 +624,7 @@ local lookup will be done in this case. Check whether the certificate described by the @var{certid} has been revoked. Due to caching, the Dirmngr is able to answer immediately in -most cases. +most cases. The @var{certid} is a hex encoded string consisting of two parts, delimited by a single dot. The first part is the SHA-1 hash of the @@ -642,7 +653,7 @@ us that it has been revoked. @item GPG_ERR_NO_CRL_KNOWN No CRL is known for this certificate or the CRL is not valid or out of -date. +date. @item GPG_ERR_NO_DATA The OCSP responder returned an ``unknown'' status. This means that it @@ -690,7 +701,7 @@ given or the certificate is not know, the function inquires the certificate using: @example - S: INQUIRE TARGETCERT + S: INQUIRE TARGETCERT C: D C: END @end example @@ -720,7 +731,7 @@ certificate is not known by Dirmngr, the function inquires the certificate using: @example - S: INQUIRE TARGETCERT + S: INQUIRE TARGETCERT C: D C: END @end example @@ -751,13 +762,13 @@ helpful for debugging. To get the actual certificate, this command immediately inquires it using @example - S: INQUIRE TARGETCERT + S: INQUIRE TARGETCERT C: D C: END @end example Thus the caller is expected to return the certificate for the request -as a binary blob. +as a binary blob. @noindent The return code is 0 for success; i.e. the certificate has not been @@ -771,45 +782,45 @@ internally by dirmngr. This command is only useful for debugging. To get the actual certificate, this command immediately inquires it using @example - S: INQUIRE TARGETCERT + S: INQUIRE TARGETCERT C: D C: END @end example Thus the caller is expected to return the certificate for the request -as a binary blob. +as a binary blob. @mansect see also @ifset isman - at command{gpgsm}(1), + at command{gpgsm}(1), @command{dirmngr-client}(1) @end ifset @include see-also-note.texi - at c + at c @c !!! UNDER CONSTRUCTION !!! - at c - at c + at c + at c @c @section Verifying a Certificate - at c + at c @c There are several ways to request services from Dirmngr. Almost all of @c them are done using the Assuan protocol. What we describe here is the @c Assuan command CHECKCRL as used for example by the dirmnr-client tool if @c invoked as - at c + at c @c @example @c dirmngr-client foo.crt @c @end example - at c + at c @c This command will send an Assuan request to an already running Dirmngr @c instance. foo.crt is expected to be a standard X.509 certificate and @c dirmngr will receive the Assuan command - at c + at c @c @example @c CHECKCRL @var [{fingerprint}] @c @end example - at c + at c @c @var{fingerprint} is optional and expected to be the SHA-1 has of the @c DER encoding of the certificate under question. It is to be HEX @c encoded. The rationale for sending the fingerprint is that it allows @@ -817,15 +828,15 @@ as a binary blob. @c this is not the case and no certificate has been found in dirmngr's @c internal certificate storage, dirmngr will request the certificate using @c the Assuan inquiry - at c + at c @c @example @c INQUIRE TARGETCERT @c @end example - at c + at c @c The caller (in our example dirmngr-client) is then expected to return @c the certificate for the request (which should match @var{fingerprint}) @c as a binary blob. - at c + at c @c Dirmngr now passes control to @code{crl_cache_cert_isvalid}. This @c function checks whether a CRL item exists for target certificate. These @c CRL items are kept in a database of already loaded and verified CRLs. @@ -837,25 +848,25 @@ as a binary blob. @c listed in the CRL or @code{GPG_ERR_NO_CRL_KNOWN} in cases where no CRL or no @c information is available. The first two codes are immediatly returned to @c the caller and the processing of this request has been done. - at c + at c @c Only the @code{GPG_ERR_NO_CRL_KNOWN} needs more attention: Dirmngr now @c calls @code{clr_cache_reload_crl} and if this succeeds calls @c @code{crl_cache_cert_isvald) once more. All further errors are @c immediately returned to the caller. - at c + at c @c @code{crl_cache_reload_crl} is the actual heart of the CRL management. @c It locates the corresponding CRL for the target certificate, reads and @c verifies this CRL and stores it in the CRL cache. It works like this: - at c + at c @c * Loop over all crlDPs in the target certificate. @c * If the crlDP is invalid immediately terminate the loop. @c * Loop over all names in the current crlDP. - at c * If the URL scheme is unknown or not enabled + at c * If the URL scheme is unknown or not enabled @c (--ignore-http-dp, --ignore-ldap-dp) continues with @c the next name. @c * @code{crl_fetch} is called to actually retrieve the CRL. @c In case of problems this name is ignore and we continue with - at c the next name. Note that @code{crl_fetch} does only return + at c the next name. Note that @code{crl_fetch} does only return @c a descriptor for the CRL for further reading so does the CRL @c does not yet end up in memory. @c * @code{crl_cache_insert} is called with that descriptor to @@ -873,16 +884,16 @@ as a binary blob. @c * @code(crl_cache_insert) is then used to actually insert the CRL @c into the cache. If this failed we give up immediatley without @c checking the rest of the servers from the first step. - at c * Ready. - at c - at c + at c * Ready. + at c + at c @c The @code{crl_cache_insert} function takes care of reading the bulk of @c the CRL, parsing it and checking the signature. It works like this: A @c new database file is created using a temporary file name. The CRL @c parsing machinery is started and all items of the CRL are put into @c this database file. At the end the issuer certificate of the CRL @c needs to be retrieved. Three cases are to be distinguished: - at c + at c @c a) An authorityKeyIdentifier with an issuer and serialno exits: The @c certificate is retrieved using @code{find_cert_bysn}. If @c the certificate is in the certificate cache, it is directly @@ -899,7 +910,7 @@ as a binary blob. @c certificate to match the requested issuer and seriano (This is @c needed because the LDAP layer may return several certificates as @c LDAP as no standard way to retrieve by serial number). - at c + at c @c b) An authorityKeyIdentifier with a key ID exists: The certificate is @c retrieved using @code{find_cert_bysubject}. If the certificate is @c in the certificate cache, it is directly returned. Then the @@ -913,7 +924,7 @@ as a binary blob. @c external resources. This is done using the @code{ca_cert_fetch} @c and @code{fetch_next_ksba_cert} and comparing the returned @c certificate to match the requested subject and key ID. - at c + at c @c c) No authorityKeyIdentifier exits: The certificate is retrieved @c using @code{find_cert_bysubject} without the key ID argument. If @c the certificate is in the certificate cache the first one with a @@ -930,12 +941,12 @@ as a binary blob. @c and @code{fetch_next_ksba_cert} and comparing the returned @c certificate to match the requested subject; the first certificate @c with a matching subject is then returned. - at c + at c @c If no certificate was found, the function returns with the error @c GPG_ERR_MISSING_CERT. Now the signature is verified. If this fails, @c the erro is returned. On success the @code{validate_cert_chain} is - at c used to verify that the certificate is actually valid. - at c + at c used to verify that the certificate is actually valid. + at c @c Here we may encounter a recursive situation: @c @code{validate_cert_chain} needs to look at other certificates and @c also at CRLs to check whether tehse other certificates and well, the @@ -944,7 +955,7 @@ as a binary blob. @c are currently processing. This would be a catch-22 and may indicate a @c broken PKI. However, due to overlapping expiring times and imprecise @c clocks thsi may actually happen. - at c + at c @c For historical reasons the Assuan command ISVALID is a bit different @c to CHECKCRL but this is mainly due to different calling conventions. @c In the end the same fucntionality is used, albeit hidden by a couple @@ -952,44 +963,44 @@ as a binary blob. @c ingetrages OCSP checking depending on options are the way it is @c called. GPGSM still uses this command but might eventuall switch over @c to CHECKCRL and CHECKOCSP so that ISVALID can be retired. - at c - at c + at c + at c @c @section Validating a certificate - at c + at c @c We describe here how the internal function @code{validate_cert_chain} @c works. Note that mainly testing purposes this functionality may be @c called directly using @cmd{dirmngr-client --validate @file{foo.crt}}. - at c + at c @c For backward compatibility this function returns success if Dirmngr is @c not used as a system daemon. Thus not validating the certicates at @c all. FIXME: This is definitely not correct and should be fixed ASAP. - at c + at c @c The function takes the target certificate and a mode argument as @c parameters and returns an error code and optionally the closes @c expiration time of all certificates in the chain. - at c + at c @c We first check that the certificate may be used for the requested @c purpose (i.e. OCSP or CRL signing). If this is not the case @c GPG_ERR_WRONG_KEY_USAGE is returned. - at c + at c @c The next step is to find the trust anchor (root certificate) and to @c assemble the chain in memory: Starting with the target certificate, @c the expiration time is checked against the current date, unknown @c critical extensions are detected and certificate policies are matched @c (We only allow 2.289.9.9 but I have no clue about that OID and from @c where I got it - it does not even seem to be assigned - debug cruft?). - at c + at c @c Now if this certificate is a self-signed one, we have reached the @c trust anchor. In this case we check that the signature is good, the @c certificate is allowed to act as a CA, that it is a trusted one (by @c checking whether it is has been put into the trusted-certs @c configuration directory) and finally prepend into to our list @c representing the certificate chain. This steps ends then. - at c + at c @c If it is not a self-signed certificate, we check that the chain won't @c get too long (current limit is 100), if this is the case we terminate @c with the error GPG_ERR_BAD_CERT_CHAIN. - at c + at c @c Now the issuer's certificate is looked up: If an @c authorityKeyIdentifier is available, this one is used to locate the @c certificate either using issuer and serialnumber or subject DN @@ -1002,7 +1013,7 @@ as a binary blob. @c that a matching certificate has explicitly been put into the @c certificate cache. If the issuer's certificate could not be found, @c the validation terminates with the error code @code{GPG_ERR_MISSING_CERT}. - at c + at c @c If the issuer's certificate has been found, the signature of the @c actual certificate is checked and in case this fails the error @c #code{GPG_ERR_BAD_CERT_CHAIN} is returned. If the signature checks out, the @@ -1011,13 +1022,13 @@ as a binary blob. @c certificate signing). Then the certificate is prepended to our list @c representing the certificate chain. Finally the loop is continued now @c with the issuer's certificate as the current certificate. - at c + at c @c After the end of the loop and if no error as been encountered @c (i.e. the certificate chain has been assempled correctly), a check is @c done whether any certificate expired or a critical policy has not been @c met. In any of these cases the validation terminates with an - at c appropriate error. - at c + at c appropriate error. + at c @c Finally the function @code{check_revocations} is called to verify no @c certificate in the assempled chain has been revoked: This is an @c recursive process because a CRL has to be checked for each certificate @@ -1025,16 +1036,16 @@ as a binary blob. @c that it is trusted and we avoid checking a CRL here due to common @c setup problems and the assumption that a revoked root certifcate has @c been removed from the list of trusted certificates. - at c - at c - at c - at c + at c + at c + at c + at c @c @section Looking up certificates through LDAP. - at c + at c @c This describes the LDAP layer to retrieve certificates. @c the functions @code{ca_cert_fetch} and @code{fetch_next_ksba_cert} are @c used for this. The first one starts a search and the second one is @c used to retrieve certificate after certificate. - at c + at c + - diff --git a/doc/gpg.texi b/doc/gpg.texi index 1a81010..bc12cbc 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -1630,16 +1630,29 @@ are available for all keyserver types, some common options are: program uses internally (libcurl, openldap, etc). @item check-cert + at ifset gpgtwoone + This option has no more function since GnuPG 2.1. Use the + @code{dirmngr} configuration options instead. + at end ifset + at ifclear gpgtwoone Enable certificate checking if the keyserver presents one (for hkps or ldaps). Defaults to on. + at end ifclear @item ca-cert-file + at ifset gpgtwoone + This option has no more function since GnuPG 2.1. Use the + @code{dirmngr} configuration options instead. + at end ifset + at ifclear gpgtwoone Provide a certificate store to override the system default. Only necessary if check-cert is enabled, and the keyserver is using a certificate that is not present in a system default certificate list. Note that depending on the SSL library that the keyserver helper is built with, this may actually be a directory or a file. + at end ifclear + @end table @item --completes-needed @code{n} commit ea0f5481f01eacedff264bf08144164aa989ec4d Author: Werner Koch Date: Mon May 5 16:06:42 2014 +0200 http: Add reference counting to the session object. * common/http.c (http_session_t): Add field "refcount". (_my_socket_new, _my_socket_ref, _my_socket_unref): Add debug code. (send_request, my_npth_read, my_npth_write): Use SOCK object for the transport ptr. (http_session_release): Factor all code out to ... (session_unref): here. Deref SOCK. (http_session_new): Init refcount and transport ptr. (http_session_ref): New. Ref and unref all assignments. -- Having the reference counted session objects makes it easier for the application to pass around only an estream. Without that the application would need to implement an es_onclose machinery for the session object. diff --git a/common/http.c b/common/http.c index 590893d..eb95dcb 100644 --- a/common/http.c +++ b/common/http.c @@ -222,6 +222,7 @@ typedef struct cookie_s *cookie_t; /* The session object. */ struct http_session_s { + int refcount; /* Number of references to this object. */ #ifdef HTTP_USE_GNUTLS gnutls_certificate_credentials_t certcred; gnutls_session_t tls_session; @@ -231,9 +232,7 @@ struct http_session_s unsigned int status; /* Verification status. */ } verify; char *servername; /* Malloced server name. */ -#else - int dummy; -#endif +#endif /*HTTP_USE_GNUTLS*/ }; @@ -327,7 +326,7 @@ init_sockets (void) /* Create a new socket object. Returns NULL and closes FD if not enough memory is available. */ static my_socket_t -my_socket_new (int fd) +_my_socket_new (int lnr, int fd) { my_socket_t so; @@ -341,34 +340,39 @@ my_socket_new (int fd) } so->fd = fd; so->refcount = 1; - /* log_debug ("my_socket_new(%d): object %p for fd %d created\n", */ + /* log_debug ("http.c:socket_new(%d): object %p for fd %d created\n", */ /* lnr, so, so->fd); */ + (void)lnr; return so; } -/* #define my_socket_new(a) _my_socket_new ((a),__LINE__) */ +#define my_socket_new(a) _my_socket_new (__LINE__, (a)) /* Bump up the reference counter for the socket object SO. */ static my_socket_t -my_socket_ref (my_socket_t so) +_my_socket_ref (int lnr, my_socket_t so) { so->refcount++; - /* log_debug ("my_socket_ref(%d): object %p for fd %d refcount now %d\n", */ + /* log_debug ("http.c:socket_ref(%d) object %p for fd %d refcount now %d\n", */ /* lnr, so, so->fd, so->refcount); */ + (void)lnr; return so; } -/* #define my_socket_ref(a) _my_socket_ref ((a),__LINE__) */ +#define my_socket_ref(a) _my_socket_ref (__LINE__,(a)) + /* Bump down the reference counter for the socket object SO. If SO has no more references, close the socket and release the object. */ static void -my_socket_unref (my_socket_t so, void (*preclose)(void*), void *preclosearg) +_my_socket_unref (int lnr, my_socket_t so, + void (*preclose)(void*), void *preclosearg) { if (so) { so->refcount--; - /* log_debug ("my_socket_unref(%d): object %p for fd %d ref now %d\n", */ + /* log_debug ("http.c:socket_unref(%d): object %p for fd %d ref now %d\n", */ /* lnr, so, so->fd, so->refcount); */ + (void)lnr; if (!so->refcount) { if (preclose) @@ -378,19 +382,21 @@ my_socket_unref (my_socket_t so, void (*preclose)(void*), void *preclosearg) } } } -/* #define my_socket_unref(a) _my_socket_unref ((a),__LINE__) */ +#define my_socket_unref(a,b,c) _my_socket_unref (__LINE__,(a),(b),(c)) #if defined (USE_NPTH) && defined(HTTP_USE_GNUTLS) static ssize_t my_npth_read (gnutls_transport_ptr_t ptr, void *buffer, size_t size) { - return npth_read ((int)(unsigned long)ptr, buffer, size); + my_socket_t sock = ptr; + return npth_read (sock->fd, buffer, size); } static ssize_t my_npth_write (gnutls_transport_ptr_t ptr, const void *buffer, size_t size) { - return npth_write ((int)(unsigned long)ptr, buffer, size); + my_socket_t sock = ptr; + return npth_write (sock->fd, buffer, size); } #endif /*USE_NPTH && HTTP_USE_GNUTLS*/ @@ -498,6 +504,44 @@ http_register_tls_ca (const char *fname) } +/* Release a session. Take care not to release it while it is being + used by a http context object. */ +static void +session_unref (int lnr, http_session_t sess) +{ + if (!sess) + return; + + sess->refcount--; + /* log_debug ("http.c:session_unref(%d): sess %p ref now %d\n", */ + /* lnr, sess, sess->refcount); */ + (void)lnr; + if (sess->refcount) + return; + +#ifdef HTTP_USE_GNUTLS + if (sess->tls_session) + { + my_socket_t sock = gnutls_transport_get_ptr (sess->tls_session); + my_socket_unref (sock, NULL, NULL); + gnutls_deinit (sess->tls_session); + } + if (sess->certcred) + gnutls_certificate_free_credentials (sess->certcred); + xfree (sess->servername); +#endif /*HTTP_USE_GNUTLS*/ + + xfree (sess); +} +#define http_session_unref(a) session_unref (__LINE__, (a)) + +void +http_session_release (http_session_t sess) +{ + http_session_unref (sess); +} + + /* Create a new session object which is currently used to enable TLS support. It may eventually allow reusing existing connections. */ gpg_error_t @@ -511,6 +555,7 @@ http_session_new (http_session_t *r_session, const char *tls_priority) sess = xtrycalloc (1, sizeof *sess); if (!sess) return gpg_error_from_syserror (); + sess->refcount = 1; #ifdef HTTP_USE_GNUTLS { @@ -544,6 +589,10 @@ http_session_new (http_session_t *r_session, const char *tls_priority) err = gpg_error (GPG_ERR_GENERAL); goto leave; } + /* A new session has the transport ptr set to (void*(-1), we need + it to be NULL. */ + gnutls_transport_set_ptr (sess->tls_session, NULL); + rc = gnutls_priority_set_direct (sess->tls_session, tls_priority? tls_priority : "NORMAL", &errpos); @@ -569,13 +618,14 @@ http_session_new (http_session_t *r_session, const char *tls_priority) (void)tls_priority; #endif /*!HTTP_USE_GNUTLS*/ + /* log_debug ("http.c:session_new: sess %p created\n", sess); */ err = 0; #ifdef HTTP_USE_GNUTLS leave: #endif /*HTTP_USE_GNUTLS*/ if (err) - http_session_release (sess); + http_session_unref (sess); else *r_session = sess; @@ -583,23 +633,13 @@ http_session_new (http_session_t *r_session, const char *tls_priority) } -/* Release a session. Take care not to release it while it is beeing - used by a http contect object. */ -void -http_session_release (http_session_t sess) +/* Increment the reference count for session SESS. */ +http_session_t +http_session_ref (http_session_t sess) { - if (!sess) - return; - -#ifdef HTTP_USE_GNUTLS - if (sess->tls_session) - gnutls_deinit (sess->tls_session); - if (sess->certcred) - gnutls_certificate_free_credentials (sess->certcred); - xfree (sess->servername); -#endif /*HTTP_USE_GNUTLS*/ - - xfree (sess); + sess->refcount++; + /* log_debug ("http.c:session_ref: sess %p ref now %d\n", sess, sess->refcount); */ + return sess; } @@ -625,7 +665,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url, return gpg_error_from_syserror (); hd->req_type = reqtype; hd->flags = flags; - hd->session = session; + hd->session = http_session_ref (session); err = parse_uri (&hd->uri, url, 0, !!(flags & HTTP_FLAG_FORCE_TLS)); if (!err) @@ -638,6 +678,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url, es_fclose (hd->fp_read); if (hd->fp_write) es_fclose (hd->fp_write); + http_session_unref (hd->session); xfree (hd); } else @@ -791,7 +832,7 @@ http_wait_response (http_t hd) if (!cookie) return gpg_err_make (default_errsource, gpg_err_code_from_syserror ()); cookie->sock = my_socket_ref (hd->sock); - cookie->session = hd->session; + cookie->session = http_session_ref (hd->session); cookie->use_tls = hd->uri->use_tls; hd->read_cookie = cookie; @@ -800,6 +841,7 @@ http_wait_response (http_t hd) { err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ()); my_socket_unref (cookie->sock, NULL, NULL); + http_session_unref (cookie->session); xfree (cookie); hd->read_cookie = NULL; return err; @@ -857,6 +899,7 @@ http_close (http_t hd, int keep_read_stream) es_fclose (hd->fp_read); if (hd->fp_write) es_fclose (hd->fp_write); + http_session_unref (hd->session); http_release_parsed_uri (hd->uri); while (hd->headers) { @@ -1431,12 +1474,7 @@ send_request (http_t hd, const char *auth, int rc; my_socket_ref (hd->sock); -#if GNUTLS_VERSION_NUMBER >= 0x030109 - gnutls_transport_set_int (hd->session->tls_session, hd->sock->fd); -#else - gnutls_transport_set_ptr (hd->session->tls_session, - (gnutls_transport_ptr_t)(hd->sock->fd)); -#endif + gnutls_transport_set_ptr (hd->session->tls_session, hd->sock); #ifdef USE_NPTH gnutls_transport_set_pull_function (hd->session->tls_session, my_npth_read); @@ -1561,7 +1599,7 @@ send_request (http_t hd, const char *auth, cookie->sock = my_socket_ref (hd->sock); hd->write_cookie = cookie; cookie->use_tls = hd->uri->use_tls; - cookie->session = hd->session; + cookie->session = http_session_ref (hd->session); hd->fp_write = es_fopencookie (cookie, "w", cookie_functions); if (!hd->fp_write) @@ -2382,6 +2420,8 @@ cookie_close (void *cookie) if (c->sock) my_socket_unref (c->sock, NULL, NULL); + if (c->session) + http_session_unref (c->session); xfree (c); return 0; } diff --git a/common/http.h b/common/http.h index fa73b6e..b6471b6 100644 --- a/common/http.h +++ b/common/http.h @@ -95,6 +95,7 @@ void http_register_tls_ca (const char *fname); gpg_error_t http_session_new (http_session_t *r_session, const char *tls_priority); +http_session_t http_session_ref (http_session_t sess); void http_session_release (http_session_t sess); diff --git a/common/t-http.c b/common/t-http.c index 0191e85..7b9c744 100644 --- a/common/t-http.c +++ b/common/t-http.c @@ -144,6 +144,7 @@ main (int argc, char **argv) int c; unsigned int my_http_flags = 0; int no_out = 0; + int tls_dbg = 0; const char *cafile = NULL; http_session_t session = NULL; @@ -163,12 +164,13 @@ main (int argc, char **argv) { fputs ("usage: " PGM " URL\n" "Options:\n" - " --verbose print timings etc.\n" - " --debug flyswatter\n" - " --cacert FNAME expect CA certificate in file FNAME\n" - " --no-verify do not verify the certificate\n" - " --force-tls use HTTP_FLAG_FORCE_TLS\n" - " --no-out do not print the content\n", + " --verbose print timings etc.\n" + " --debug flyswatter\n" + " --gnutls-debug N use GNUTLS debug level N\n" + " --cacert FNAME expect CA certificate in file FNAME\n" + " --no-verify do not verify the certificate\n" + " --force-tls use HTTP_FLAG_FORCE_TLS\n" + " --no-out do not print the content\n", stdout); exit (0); } @@ -183,6 +185,15 @@ main (int argc, char **argv) debug++; argc--; argv++; } + else if (!strcmp (*argv, "--gnutls-debug")) + { + argc--; argv++; + if (argc) + { + tls_dbg = atoi (*argv); + argc--; argv++; + } + } else if (!strcmp (*argv, "--cacert")) { argc--; argv++; @@ -248,7 +259,8 @@ main (int argc, char **argv) /* gnutls_certificate_set_dh_params (certcred, dh_params); */ gnutls_global_set_log_function (my_gnutls_log); - /* gnutls_global_set_log_level (2); */ + if (tls_dbg) + gnutls_global_set_log_level (tls_dbg); #endif /*HTTP_USE_GNUTLS*/ commit 0e59195642eb26263b8e0b9200290538631d35cd Author: Werner Koch Date: Fri May 2 15:37:02 2014 +0200 http: Add HTTP_FLAG_FORCE_TLS and http_get_tls_info. * common/http.c (http_parse_uri): Factor code out to ... (parse_uri): here. Add arg FORCE_TLS. (do_parse_uri): Ditto. Implement flag. (http_get_tls_info): New. (http_register_tls_ca): Allow clearing of the list. (send_request): Use a default verification function. * common/http.h (HTTP_FLAG_FORCE_TLS): New. * common/t-http.c (main): Add several command line options. diff --git a/common/http.c b/common/http.c index e5516e8..590893d 100644 --- a/common/http.c +++ b/common/http.c @@ -161,7 +161,9 @@ typedef void * gnutls_session_t; #endif static gpg_err_code_t do_parse_uri (parsed_uri_t uri, int only_local_part, - int no_scheme_check); + int no_scheme_check, int force_tls); +static gpg_error_t parse_uri (parsed_uri_t *ret_uri, const char *uri, + int no_scheme_check, int force_tls); static int remove_escapes (char *string); static int insert_escapes (char *buffer, const char *string, const char *special); @@ -463,7 +465,9 @@ make_header_line (const char *prefix, const char *suffix, -/* Register the global TLS callback fucntion. */ +/* Register a non-standard global TLS callback function. If no + verification is desired a callback needs to be registered which + always returns NULL. */ void http_register_tls_callback (gpg_error_t (*cb)(http_t, http_session_t, int)) { @@ -473,15 +477,24 @@ http_register_tls_callback (gpg_error_t (*cb)(http_t, http_session_t, int)) /* Register a CA certificate for future use. The certificate is expected to be in FNAME. PEM format is assume if FNAME has a - suffix of ".pem" */ + suffix of ".pem". If FNAME is NULL the list of CA files is + removed. */ void http_register_tls_ca (const char *fname) { strlist_t sl; - sl = add_to_strlist (&tls_ca_certlist, fname); - if (*sl->d && !strcmp (sl->d + strlen (sl->d) - 4, ".pem")) - sl->flags = 1; + if (!fname) + { + free_strlist (tls_ca_certlist); + tls_ca_certlist = NULL; + } + else + { + sl = add_to_strlist (&tls_ca_certlist, fname); + if (*sl->d && !strcmp (sl->d + strlen (sl->d) - 4, ".pem")) + sl->flags = 1; + } } @@ -614,7 +627,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url, hd->flags = flags; hd->session = session; - err = http_parse_uri (&hd->uri, url, 0); + err = parse_uri (&hd->uri, url, 0, !!(flags & HTTP_FLAG_FORCE_TLS)); if (!err) err = send_request (hd, auth, proxy, srvtag, headers); @@ -875,17 +888,29 @@ http_get_status_code (http_t hd) return hd?hd->status_code:0; } +/* Return information pertaining to TLS. If TLS is not in use for HD, + NULL is returned. WHAT is used ask for specific information: - -/* - * Parse an URI and put the result into the newly allocated RET_URI. - * On success the caller must use release_parsed_uri() to releases the - * resources. If NO_SCHEME_CHECK is set, the function tries to parse - * the URL in the same way it would do for an HTTP style URI. + (NULL) := Only check whether TLS is is use. Returns an + unspecified string if TLS is in use. That string may + even be the empty string. */ -gpg_error_t -http_parse_uri (parsed_uri_t *ret_uri, const char *uri, - int no_scheme_check) +const char * +http_get_tls_info (http_t hd, const char *what) +{ + (void)what; + + if (!hd) + return NULL; + + return hd->uri->use_tls? "":NULL; +} + + + +static gpg_error_t +parse_uri (parsed_uri_t *ret_uri, const char *uri, + int no_scheme_check, int force_tls) { gpg_err_code_t ec; @@ -893,7 +918,7 @@ http_parse_uri (parsed_uri_t *ret_uri, const char *uri, if (!*ret_uri) return gpg_err_make (default_errsource, gpg_err_code_from_syserror ()); strcpy ((*ret_uri)->buffer, uri); - ec = do_parse_uri (*ret_uri, 0, no_scheme_check); + ec = do_parse_uri (*ret_uri, 0, no_scheme_check, force_tls); if (ec) { xfree (*ret_uri); @@ -902,6 +927,21 @@ http_parse_uri (parsed_uri_t *ret_uri, const char *uri, return gpg_err_make (default_errsource, ec); } + +/* + * Parse an URI and put the result into the newly allocated RET_URI. + * On success the caller must use release_parsed_uri() to releases the + * resources. If NO_SCHEME_CHECK is set, the function tries to parse + * the URL in the same way it would do for an HTTP style URI. + */ +gpg_error_t +http_parse_uri (parsed_uri_t *ret_uri, const char *uri, + int no_scheme_check) +{ + return parse_uri (ret_uri, uri, no_scheme_check, 0); +} + + void http_release_parsed_uri (parsed_uri_t uri) { @@ -920,7 +960,8 @@ http_release_parsed_uri (parsed_uri_t uri) static gpg_err_code_t -do_parse_uri (parsed_uri_t uri, int only_local_part, int no_scheme_check) +do_parse_uri (parsed_uri_t uri, int only_local_part, + int no_scheme_check, int force_tls) { uri_tuple_t *tail; char *p, *p2, *p3, *pp; @@ -951,18 +992,20 @@ do_parse_uri (parsed_uri_t uri, int only_local_part, int no_scheme_check) for (pp=p; *pp; pp++) *pp = tolower (*(unsigned char*)pp); uri->scheme = p; - if (!strcmp (uri->scheme, "http")) + if (!strcmp (uri->scheme, "http") && !force_tls) { uri->port = 80; uri->is_http = 1; } - else if (!strcmp (uri->scheme, "hkp")) + else if (!strcmp (uri->scheme, "hkp") && !force_tls) { uri->port = 11371; uri->is_http = 1; } #ifdef HTTP_USE_GNUTLS - else if (!strcmp (uri->scheme, "https") || !strcmp (uri->scheme,"hkps")) + else if (!strcmp (uri->scheme, "https") || !strcmp (uri->scheme,"hkps") + || (force_tls && (!strcmp (uri->scheme, "http") + || !strcmp (uri->scheme,"hkp")))) { uri->port = 443; uri->is_http = 1; @@ -1329,7 +1372,8 @@ send_request (http_t hd, const char *auth, if (proxy) http_proxy = proxy; - err = http_parse_uri (&uri, http_proxy, 0); + err = parse_uri (&uri, http_proxy, 0, + !!(hd->flags & HTTP_FLAG_FORCE_TLS)); if (err) { log_error ("invalid HTTP proxy (%s): %s\n", @@ -1412,17 +1456,17 @@ send_request (http_t hd, const char *auth, return gpg_err_make (default_errsource, GPG_ERR_NETWORK); } + hd->session->verify.done = 0; if (tls_callback) + err = tls_callback (hd, hd->session, 0); + else + err = http_verify_server_credentials (hd->session); + if (err) { - hd->session->verify.done = 0; - err = tls_callback (hd, hd->session, 0); - if (err) - { - log_info ("TLS connection authentication failed: %s\n", - gpg_strerror (err)); - xfree (proxy_authstr); - return err; - } + log_info ("TLS connection authentication failed: %s\n", + gpg_strerror (err)); + xfree (proxy_authstr); + return err; } } #endif /*HTTP_USE_GNUTLS*/ diff --git a/common/http.h b/common/http.h index e38fadc..fa73b6e 100644 --- a/common/http.h +++ b/common/http.h @@ -77,6 +77,7 @@ enum HTTP_FLAG_TRY_PROXY = 1, /* Try to use a proxy. */ HTTP_FLAG_SHUTDOWN = 2, /* Close sending end after the request. */ HTTP_FLAG_LOG_RESP = 8, /* Log the server respone. */ + HTTP_FLAG_FORCE_TLS = 16, /* Force the use opf TLS. */ HTTP_FLAG_IGNORE_CL = 32, /* Ignore content-length. */ HTTP_FLAG_IGNORE_IPv4 = 64, /* Do not use IPv4. */ HTTP_FLAG_IGNORE_IPv6 = 128 /* Do not use IPv6. */ @@ -133,6 +134,7 @@ gpg_error_t http_open_document (http_t *r_hd, estream_t http_get_read_ptr (http_t hd); estream_t http_get_write_ptr (http_t hd); unsigned int http_get_status_code (http_t hd); +const char *http_get_tls_info (http_t hd, const char *what); const char *http_get_header (http_t hd, const char *name); const char **http_get_header_names (http_t hd); gpg_error_t http_verify_server_credentials (http_session_t sess); diff --git a/common/t-http.c b/common/t-http.c index f515287..0191e85 100644 --- a/common/t-http.c +++ b/common/t-http.c @@ -46,7 +46,11 @@ # include /* For init, logging, and deinit. */ #endif /*HTTP_USE_GNUTLS*/ +#define PGM "t-http" +static int verbose; +static int debug; +static int no_verify; /* static void */ /* read_dh_params (const char *fname) */ @@ -98,7 +102,7 @@ verify_callback (http_t hd, http_session_t session, int reserved) { (void)hd; (void)reserved; - return http_verify_server_credentials (session); + return no_verify? 0 : http_verify_server_credentials (session); } @@ -131,23 +135,92 @@ prepend_srcdir (const char *fname) int main (int argc, char **argv) { + int last_argc = -1; gpg_error_t err; int rc; parsed_uri_t uri; uri_tuple_t r; http_t hd; int c; + unsigned int my_http_flags = 0; + int no_out = 0; + const char *cafile = NULL; http_session_t session = NULL; es_init (); - log_set_prefix ("t-http", 1 | 4); - if (argc != 2) + log_set_prefix (PGM, 1 | 4); + if (argc) + { argc--; argv++; } + while (argc && last_argc != argc ) { - fprintf (stderr, "usage: t-http uri\n"); - return 1; + last_argc = argc; + if (!strcmp (*argv, "--")) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--help")) + { + fputs ("usage: " PGM " URL\n" + "Options:\n" + " --verbose print timings etc.\n" + " --debug flyswatter\n" + " --cacert FNAME expect CA certificate in file FNAME\n" + " --no-verify do not verify the certificate\n" + " --force-tls use HTTP_FLAG_FORCE_TLS\n" + " --no-out do not print the content\n", + stdout); + exit (0); + } + else if (!strcmp (*argv, "--verbose")) + { + verbose++; + argc--; argv++; + } + else if (!strcmp (*argv, "--debug")) + { + verbose += 2; + debug++; + argc--; argv++; + } + else if (!strcmp (*argv, "--cacert")) + { + argc--; argv++; + if (argc) + { + cafile = *argv; + argc--; argv++; + } + } + else if (!strcmp (*argv, "--no-verify")) + { + no_verify = 1; + argc--; argv++; + } + else if (!strcmp (*argv, "--force-tls")) + { + my_http_flags |= HTTP_FLAG_FORCE_TLS; + argc--; argv++; + } + else if (!strcmp (*argv, "--no-out")) + { + no_out = 1; + argc--; argv++; + } + else if (!strncmp (*argv, "--", 2)) + { + fprintf (stderr, PGM ": unknown option '%s'\n", *argv); + exit (1); + } + } + if (argc != 1) + { + fprintf (stderr, PGM ": no or roo many URLS given\n"); + exit (1); } - argc--; - argv++; + + if (!cafile) + cafile = prepend_srcdir ("tls-ca.pem"); #ifdef HTTP_USE_GNUTLS rc = gnutls_global_init (); @@ -155,7 +228,7 @@ main (int argc, char **argv) log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc)); http_register_tls_callback (verify_callback); - http_register_tls_ca (prepend_srcdir ("tls-ca.pem")); + http_register_tls_ca (cafile); err = http_session_new (&session, NULL); if (err) @@ -217,11 +290,17 @@ main (int argc, char **argv) } putchar ('\n'); } + printf ("TLS : %s\n", + uri->use_tls? "yes": + (my_http_flags&HTTP_FLAG_FORCE_TLS)? "forced" : "no"); + } + fflush (stdout); http_release_parsed_uri (uri); uri = NULL; - rc = http_open_document (&hd, *argv, NULL, 0, NULL, session, NULL, NULL); + rc = http_open_document (&hd, *argv, NULL, my_http_flags, + NULL, session, NULL, NULL); if (rc) { log_error ("can't get '%s': %s\n", *argv, gpg_strerror (rc)); @@ -242,6 +321,7 @@ main (int argc, char **argv) printf ("HDR: %s: %s\n", names[i], http_get_header (hd, names[i])); xfree (names); } + fflush (stdout); switch (http_get_status_code (hd)) { @@ -250,12 +330,21 @@ main (int argc, char **argv) case 401: case 403: case 404: - while ((c = es_getc (http_get_read_ptr (hd))) != EOF) - putchar (c); + { + unsigned long count = 0; + while ((c = es_getc (http_get_read_ptr (hd))) != EOF) + { + count++; + if (!no_out) + putchar (c); + } + log_info ("Received bytes: %lu\n", count); + } break; case 301: case 302: - printf ("Redirected to '%s'\n", http_get_header (hd, "Location")); + case 307: + log_info ("Redirected to: %s\n", http_get_header (hd, "Location")); break; } http_close (hd, 0); ----------------------------------------------------------------------- Summary of changes: common/http.c | 226 ++++++++++++++++++++++++++------------ common/http.h | 3 + common/t-http.c | 127 ++++++++++++++++++--- dirmngr/dirmngr.c | 47 ++++++++ dirmngr/ks-engine-hkp.c | 27 ++++- dirmngr/sks-keyservers.netCA.pem | 32 ++++++ doc/dirmngr.texi | 145 +++++++++++++----------- doc/gpg.texi | 13 +++ 8 files changed, 466 insertions(+), 154 deletions(-) create mode 100644 dirmngr/sks-keyservers.netCA.pem hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Wed May 7 03:08:56 2014 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Wed, 07 May 2014 03:08:56 +0200 Subject: [git] Poldi - branch, master, updated. release-0.4.1-31-g49a1cab 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 "PAM for the OpenPGP card". The branch, master has been updated via 49a1cab533d43cc6a9aff3ded95105b7afad4198 (commit) from ba7154bea83ba8b4888b9f733ee0de71deb6f3e4 (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 49a1cab533d43cc6a9aff3ded95105b7afad4198 Author: NIIBE Yutaka Date: Wed May 7 10:10:38 2014 +0900 SCD: fix for pinpad. * src/scd/scd.c (inq_needpin): It's now PINPAD. diff --git a/src/scd/scd.c b/src/scd/scd.c index d54b47e..52a64f4 100644 --- a/src/scd/scd.c +++ b/src/scd/scd.c @@ -727,7 +727,7 @@ inq_needpin (void *opaque, const char *line) rc = assuan_send_data (parm->ctx->assuan_ctx, pin, pinlen); xfree (pin); } - else if (!strncmp (line, "POPUPKEYPADPROMPT", 17) + else if (!strncmp (line, "POPUPPINPADPROMPT", 17) && (line[17] == ' ' || !line[17])) { if (!parm->getpin_cb) @@ -742,7 +742,7 @@ inq_needpin (void *opaque, const char *line) rc = parm->getpin_cb (parm->getpin_cb_arg, line, NULL, 1); } - else if (!strncmp (line, "DISMISSKEYPADPROMPT", 19) + else if (!strncmp (line, "DISMISSPINPADPROMPT", 19) && (line[19] == ' ' || !line[19])) { if (!parm->getpin_cb) ----------------------------------------------------------------------- Summary of changes: src/scd/scd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- PAM for the OpenPGP card http://git.gnupg.org From cvs at cvs.gnupg.org Wed May 7 10:32:43 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 07 May 2014 10:32:43 +0200 Subject: [git] GCRYPT - branch, LIBGCRYPT-1-6-BRANCH, updated. libgcrypt-1.6.1-9-ge438beb 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, LIBGCRYPT-1-6-BRANCH has been updated via e438beb82565dc777406ef4b847dcca33e0ad2d8 (commit) via 75c1db9d12ccd28b167a9cd8dc1ace6240e20d02 (commit) from 06b4192efdd93fa59d76bf731da9829f01b04294 (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 e438beb82565dc777406ef4b847dcca33e0ad2d8 Author: Werner Koch Date: Thu Jan 9 19:14:09 2014 +0100 Support building using the latest mingw-w64 toolchain. * acinclude.m4 (GNUPG_SYS_SYMBOL_UNDERSCORE): Change mingw detection. -- This patch is related to Debian-bug-id 730271 for GnuPG 1.4: From: Stephen Kitt All MinGW targets require underscores when linking. This patch fixes acinclude.m4 and the resulting configure so they don't limit the use of underscores to the old mingw32msvc targets. Signed-off-by: Werner Koch diff --git a/acinclude.m4 b/acinclude.m4 index fdb2d17..0791b84 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -101,7 +101,7 @@ AC_DEFUN([GNUPG_CHECK_GNUMAKE], AC_DEFUN([GNUPG_SYS_SYMBOL_UNDERSCORE], [tmp_do_check="no" case "${host}" in - *-mingw32msvc*) + *-mingw32*) ac_cv_sys_symbol_underscore=yes ;; i386-emx-os2 | i[3456]86-pc-os2*emx | i386-pc-msdosdjgpp) commit 75c1db9d12ccd28b167a9cd8dc1ace6240e20d02 Author: Werner Koch Date: Thu Jan 9 19:14:09 2014 +0100 Use internal malloc function in fips.c * src/fips.c (check_binary_integrity): s/gcry_malloc/xtrymalloc/. -- This fixes a build problem with ENABLE_HMAC_BINARY_CHECK. Reported-by: Michal Vyskocil. diff --git a/src/fips.c b/src/fips.c index 8148dcd..3ab33f9 100644 --- a/src/fips.c +++ b/src/fips.c @@ -602,7 +602,7 @@ check_binary_integrity (void) err = gpg_error (GPG_ERR_INTERNAL); else { - fname = gcry_malloc (strlen (info.dli_fname) + 1 + 5 + 1 ); + fname = xtrymalloc (strlen (info.dli_fname) + 1 + 5 + 1 ); if (!fname) err = gpg_error_from_syserror (); else ----------------------------------------------------------------------- Summary of changes: acinclude.m4 | 2 +- src/fips.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Wed May 7 13:28:27 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 07 May 2014 13:28:27 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-65-gfc6ff6f 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 fc6ff6f73a51bcbbbb3757dc1386da40aa3ae75d (commit) from a79c4ad7c56ee4410f17beb73eeb58b0dd36bfc6 (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 fc6ff6f73a51bcbbbb3757dc1386da40aa3ae75d Author: Werner Koch Date: Wed May 7 11:05:36 2014 +0200 Bump LT version. * configure.ac: Bumb LT version to C21/A1/R0. -- This is to avoid conflicts with the 1.6 series. Note that if we add a new interface to 1.6 we would need to bump age again. diff --git a/configure.ac b/configure.ac index 79f79ef..6539a96 100644 --- a/configure.ac +++ b/configure.ac @@ -51,11 +51,12 @@ m4_define([mym4_full_version],[mym4_version[]mym4_betastring]) AC_INIT([libgcrypt],[mym4_full_version],[http://bugs.gnupg.org]) # LT Version numbers, remember to change them just *before* a release. +# ====== NOTE: Already bumped to 21/1/0 for the 1.7.0 release. ==== # (Interfaces removed: CURRENT++, AGE=0, REVISION=0) # (Interfaces added: CURRENT++, AGE++, REVISION=0) # (No interfaces changed: REVISION++) -LIBGCRYPT_LT_CURRENT=20 -LIBGCRYPT_LT_AGE=0 +LIBGCRYPT_LT_CURRENT=21 +LIBGCRYPT_LT_AGE=1 LIBGCRYPT_LT_REVISION=0 ----------------------------------------------------------------------- Summary of changes: configure.ac | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Wed May 7 15:06:56 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 07 May 2014 15:06:56 +0200 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-413-g359c643 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 359c643d747c890f73f68b42e0aeb896016f05fd (commit) via e73edfb1759d05121ea66f67c775e763bf47d737 (commit) via e5279c85a04084a2277acb224bd4ca3026dcafd4 (commit) via 09055aa0f7993aaf4dcffdd80d8192945ae6080a (commit) via 8fee6c1ce6d116fe7909dbe1184d95bc91305484 (commit) via bdb9c2b314400da9155b8a924e22e486793dda89 (commit) via a63ed9875830e5b3b4d48b7d97d24c18de36b326 (commit) via 6477e51919ef97f0f9cc05d10cdc7aa2b89faafe (commit) from 60e2fc7d38d8b37d1de944cf230e410c2ce37d5e (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 359c643d747c890f73f68b42e0aeb896016f05fd Author: Werner Koch Date: Wed May 7 15:05:34 2014 +0200 gpg: Print the key algorithm/curve with signature info. * g10/mainproc.c (check_sig_and_print): Print the name and curve. diff --git a/g10/mainproc.c b/g10/mainproc.c index d4a0549..28bb05e 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -1564,6 +1564,9 @@ check_sig_and_print (CTX c, KBNODE node) int rc; int is_expkey = 0; int is_revkey = 0; + char pkstrbuf[PUBKEY_STRING_SIZE]; + + *pkstrbuf = 0; if (opt.skip_verify) { @@ -1843,6 +1846,8 @@ check_sig_and_print (CTX c, KBNODE node) log_printf (" [%s]\n",trust_value_to_string(valid)); else log_printf ("\n"); + + pubkey_string (pk, pkstrbuf, sizeof pkstrbuf); count++; } @@ -2017,10 +2022,12 @@ check_sig_and_print (CTX c, KBNODE node) log_info (_("Signature expires %s\n"), asctimestamp(sig->expiredate)); if (opt.verbose) - log_info (_("%s signature, digest algorithm %s\n"), + log_info (_("%s signature, digest algorithm %s%s%s\n"), sig->sig_class==0x00?_("binary"): sig->sig_class==0x01?_("textmode"):_("unknown"), - gcry_md_algo_name (sig->digest_algo)); + gcry_md_algo_name (sig->digest_algo), + *pkstrbuf?", key algorithm ":"", + pkstrbuf); if (rc) g10_errors_seen = 1; commit e73edfb1759d05121ea66f67c775e763bf47d737 Author: Werner Koch Date: Wed May 7 14:36:34 2014 +0200 gpg: Fix memleak in signature verification of bogus keys. * g10/mainproc.c (check_sig_and_print): Factor common code out to ... (print_good_bad_signature): here. -- P was not released if the key had no user id. diff --git a/g10/mainproc.c b/g10/mainproc.c index 20a799f..d4a0549 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -1528,12 +1528,42 @@ pka_uri_from_sig (PKT_signature *sig) } +static void +print_good_bad_signature (int statno, const char *keyid_str, kbnode_t un, + PKT_signature *sig, int rc) +{ + char *p; + + write_status_text_and_buffer (statno, keyid_str, + un? un->pkt->pkt.user_id->name:"[?]", + un? un->pkt->pkt.user_id->len:3, + -1); + + if (un) + p = utf8_to_native (un->pkt->pkt.user_id->name, + un->pkt->pkt.user_id->len, 0); + else + p = xstrdup ("[?]"); + + if (rc) + log_info (_("BAD signature from \"%s\""), p); + else if (sig->flags.expired) + log_info (_("Expired signature from \"%s\""), p); + else + log_info (_("Good signature from \"%s\""), p); + + xfree (p); +} + + static int check_sig_and_print (CTX c, KBNODE node) { PKT_signature *sig = node->pkt->pkt.signature; const char *astr; - int rc, is_expkey=0, is_revkey=0; + int rc; + int is_expkey = 0; + int is_revkey = 0; if (opt.skip_verify) { @@ -1663,7 +1693,7 @@ check_sig_and_print (CTX c, KBNODE node) asctimestamp(sig->timestamp), astr? astr: "?", keystr(sig->keyid)); - rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); + rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey ); /* If the key isn't found, check for a preferred keyserver */ @@ -1778,7 +1808,6 @@ check_sig_and_print (CTX c, KBNODE node) /* Find and print the primary user ID. */ for (un=keyblock; un; un = un->next) { - char *p; int valid; if (un->pkt->pkttype==PKT_PUBLIC_KEY) @@ -1807,24 +1836,10 @@ check_sig_and_print (CTX c, KBNODE node) valid = get_validity (pk, un->pkt->pkt.user_id); keyid_str[17] = 0; /* cut off the "[uncertain]" part */ - write_status_text_and_buffer (statno, keyid_str, - un->pkt->pkt.user_id->name, - un->pkt->pkt.user_id->len, - -1); - - p = utf8_to_native (un->pkt->pkt.user_id->name, - un->pkt->pkt.user_id->len, 0); - - if (rc) - log_info (_("BAD signature from \"%s\""), p); - else if (sig->flags.expired) - log_info (_("Expired signature from \"%s\""), p); - else - log_info (_("Good signature from \"%s\""), p); - xfree(p); + print_good_bad_signature (statno, keyid_str, un, sig, rc); - if (opt.verify_options&VERIFY_SHOW_UID_VALIDITY) + if ((opt.verify_options & VERIFY_SHOW_UID_VALIDITY)) log_printf (" [%s]\n",trust_value_to_string(valid)); else log_printf ("\n"); @@ -1833,8 +1848,6 @@ check_sig_and_print (CTX c, KBNODE node) if (!count) /* Just in case that we have no valid textual userid */ { - char *p; - /* Try for an invalid textual userid */ for (un=keyblock; un; un = un->next) { @@ -1856,23 +1869,8 @@ check_sig_and_print (CTX c, KBNODE node) if (opt.trust_model==TM_ALWAYS || !un) keyid_str[17] = 0; /* cut off the "[uncertain]" part */ - write_status_text_and_buffer (statno, keyid_str, - un? un->pkt->pkt.user_id->name:"[?]", - un? un->pkt->pkt.user_id->len:3, - -1 ); - - if (un) - p= utf8_to_native (un->pkt->pkt.user_id->name, - un->pkt->pkt.user_id->len, 0); - else - p = xstrdup ("[?]"); + print_good_bad_signature (statno, keyid_str, un, sig, rc); - if (rc) - log_info (_("BAD signature from \"%s\""), p); - else if (sig->flags.expired) - log_info (_("Expired signature from \"%s\""), p); - else - log_info (_("Good signature from \"%s\""), p); if (opt.trust_model != TM_ALWAYS && un) log_printf (" %s",_("[uncertain]") ); log_printf ("\n"); commit e5279c85a04084a2277acb224bd4ca3026dcafd4 Author: Werner Koch Date: Wed May 7 14:08:16 2014 +0200 gpg: Fix indendation of check_sig_and_print. -- diff --git a/g10/mainproc.c b/g10/mainproc.c index f830eee..20a799f 100644 --- a/g10/mainproc.c +++ b/g10/mainproc.c @@ -1,7 +1,7 @@ /* mainproc.c - handle packets * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, * 2008, 2009 Free Software Foundation, Inc. - * Copyright (C) 2013 Werner Koch + * Copyright (C) 2013, 2014 Werner Koch * * This file is part of GnuPG. * @@ -1529,7 +1529,7 @@ pka_uri_from_sig (PKT_signature *sig) static int -check_sig_and_print( CTX c, KBNODE node ) +check_sig_and_print (CTX c, KBNODE node) { PKT_signature *sig = node->pkt->pkt.signature; const char *astr; @@ -1649,390 +1649,405 @@ check_sig_and_print( CTX c, KBNODE node ) log_error(_("can't handle this ambiguous signature data\n")); return 0; } - } - /* (Indendation below not yet changed to GNU style.) */ + astr = openpgp_pk_algo_name ( sig->pubkey_algo ); + if (keystrlen () > 8) + { + log_info (_("Signature made %s\n"), asctimestamp(sig->timestamp)); + log_info (_(" using %s key %s\n"), + astr? astr: "?",keystr(sig->keyid)); + } + else + log_info (_("Signature made %s using %s key ID %s\n"), + asctimestamp(sig->timestamp), astr? astr: "?", + keystr(sig->keyid)); - astr = openpgp_pk_algo_name ( sig->pubkey_algo ); - if(keystrlen()>8) - { - log_info(_("Signature made %s\n"),asctimestamp(sig->timestamp)); - log_info(_(" using %s key %s\n"), - astr? astr: "?",keystr(sig->keyid)); - } - else - log_info(_("Signature made %s using %s key ID %s\n"), - asctimestamp(sig->timestamp), astr? astr: "?", - keystr(sig->keyid)); + rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); - rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); + /* If the key isn't found, check for a preferred keyserver */ - /* If the key isn't found, check for a preferred keyserver */ + if (gpg_err_code (rc) == G10ERR_NO_PUBKEY && sig->flags.pref_ks) + { + const byte *p; + int seq = 0; + size_t n; - if(rc==G10ERR_NO_PUBKEY && sig->flags.pref_ks) - { - const byte *p; - int seq=0; - size_t n; + while ((p=enum_sig_subpkt (sig->hashed,SIGSUBPKT_PREF_KS,&n,&seq,NULL))) + { + /* According to my favorite copy editor, in English grammar, + you say "at" if the key is located on a web page, but + "from" if it is located on a keyserver. I'm not going to + even try to make two strings here :) */ + log_info(_("Key available at: ") ); + print_utf8_buffer (log_get_stream(), p, n); + log_printf ("\n"); + + if (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE + && opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL) + { + struct keyserver_spec *spec; - while((p=enum_sig_subpkt(sig->hashed,SIGSUBPKT_PREF_KS,&n,&seq,NULL))) - { - /* According to my favorite copy editor, in English - grammar, you say "at" if the key is located on a web - page, but "from" if it is located on a keyserver. I'm - not going to even try to make two strings here :) */ - log_info(_("Key available at: ") ); - print_utf8_buffer (log_get_stream(), p, n); - log_printf ("\n"); - - if(opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE - && opt.keyserver_options.options&KEYSERVER_HONOR_KEYSERVER_URL) - { - struct keyserver_spec *spec; + spec = parse_preferred_keyserver (sig); + if (spec) + { + int res; - spec=parse_preferred_keyserver(sig); - if(spec) - { - int res; + glo_ctrl.in_auto_key_retrieve++; + res = keyserver_import_keyid (c->ctrl, sig->keyid,spec); + glo_ctrl.in_auto_key_retrieve--; + if (!res) + rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); + free_keyserver_spec (spec); - glo_ctrl.in_auto_key_retrieve++; - res = keyserver_import_keyid (c->ctrl, sig->keyid,spec); - glo_ctrl.in_auto_key_retrieve--; - if(!res) - rc=do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); - free_keyserver_spec(spec); - - if(!rc) - break; - } - } - } - } + if (!rc) + break; + } + } + } + } - /* If the preferred keyserver thing above didn't work, our second - try is to use the URI from a DNS PKA record. */ - if ( rc == G10ERR_NO_PUBKEY - && opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE - && opt.keyserver_options.options&KEYSERVER_HONOR_PKA_RECORD) - { - const char *uri = pka_uri_from_sig (sig); + /* If the preferred keyserver thing above didn't work, our second + try is to use the URI from a DNS PKA record. */ + if (gpg_err_code (rc) == G10ERR_NO_PUBKEY + && (opt.keyserver_options.options & KEYSERVER_AUTO_KEY_RETRIEVE) + && (opt.keyserver_options.options & KEYSERVER_HONOR_PKA_RECORD)) + { + const char *uri = pka_uri_from_sig (sig); - if (uri) - { - /* FIXME: We might want to locate the key using the - fingerprint instead of the keyid. */ - int res; - struct keyserver_spec *spec; + if (uri) + { + /* FIXME: We might want to locate the key using the + fingerprint instead of the keyid. */ + int res; + struct keyserver_spec *spec; - spec = parse_keyserver_uri (uri, 1, NULL, 0); - if (spec) - { - glo_ctrl.in_auto_key_retrieve++; - res = keyserver_import_keyid (c->ctrl, sig->keyid, spec); + spec = parse_keyserver_uri (uri, 1, NULL, 0); + if (spec) + { + glo_ctrl.in_auto_key_retrieve++; + res = keyserver_import_keyid (c->ctrl, sig->keyid, spec); glo_ctrl.in_auto_key_retrieve--; free_keyserver_spec (spec); if (!res) - rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); - } - } - } + rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey ); + } + } + } - /* If the preferred keyserver thing above didn't work and we got + /* If the preferred keyserver thing above didn't work and we got no information from the DNS PKA, this is a third try. */ - if( rc == G10ERR_NO_PUBKEY && opt.keyserver - && opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE) - { - int res; + if (gpg_err_code (rc) == G10ERR_NO_PUBKEY + && opt.keyserver + && (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)) + { + int res; - glo_ctrl.in_auto_key_retrieve++; - res=keyserver_import_keyid (c->ctrl, sig->keyid, opt.keyserver ); - glo_ctrl.in_auto_key_retrieve--; - if(!res) - rc = do_check_sig(c, node, NULL, &is_expkey, &is_revkey ); - } + glo_ctrl.in_auto_key_retrieve++; + res=keyserver_import_keyid (c->ctrl, sig->keyid, opt.keyserver ); + glo_ctrl.in_auto_key_retrieve--; + if (!res) + rc = do_check_sig (c, node, NULL, &is_expkey, &is_revkey ); + } - if( !rc || gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE ) { - KBNODE un, keyblock; - int count=0, statno; - char keyid_str[50]; - PKT_public_key *pk=NULL; - - if(rc) - statno=STATUS_BADSIG; - else if(sig->flags.expired) - statno=STATUS_EXPSIG; - else if(is_expkey) - statno=STATUS_EXPKEYSIG; - else if(is_revkey) - statno=STATUS_REVKEYSIG; - else - statno=STATUS_GOODSIG; + if (!rc || gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE) + { + kbnode_t un, keyblock; + int count = 0; + int statno; + char keyid_str[50]; + PKT_public_key *pk = NULL; + + if (rc) + statno = STATUS_BADSIG; + else if (sig->flags.expired) + statno = STATUS_EXPSIG; + else if (is_expkey) + statno = STATUS_EXPKEYSIG; + else if(is_revkey) + statno = STATUS_REVKEYSIG; + else + statno = STATUS_GOODSIG; + + keyblock = get_pubkeyblock (sig->keyid); + + snprintf (keyid_str, sizeof keyid_str, "%08lX%08lX [uncertain] ", + (ulong)sig->keyid[0], (ulong)sig->keyid[1]); + + /* Find and print the primary user ID. */ + for (un=keyblock; un; un = un->next) + { + char *p; + int valid; - keyblock = get_pubkeyblock( sig->keyid ); + if (un->pkt->pkttype==PKT_PUBLIC_KEY) + { + pk=un->pkt->pkt.public_key; + continue; + } + if (un->pkt->pkttype != PKT_USER_ID) + continue; + if (!un->pkt->pkt.user_id->created) + continue; + if (un->pkt->pkt.user_id->is_revoked) + continue; + if (un->pkt->pkt.user_id->is_expired) + continue; + if (!un->pkt->pkt.user_id->is_primary) + continue; + /* We want the textual primary user ID here */ + if (un->pkt->pkt.user_id->attrib_data) + continue; - sprintf (keyid_str, "%08lX%08lX [uncertain] ", - (ulong)sig->keyid[0], (ulong)sig->keyid[1]); + assert (pk); - /* find and print the primary user ID */ - for( un=keyblock; un; un = un->next ) { - char *p; - int valid; - if(un->pkt->pkttype==PKT_PUBLIC_KEY) - { - pk=un->pkt->pkt.public_key; - continue; - } - if( un->pkt->pkttype != PKT_USER_ID ) - continue; - if ( !un->pkt->pkt.user_id->created ) - continue; - if ( un->pkt->pkt.user_id->is_revoked ) - continue; - if ( un->pkt->pkt.user_id->is_expired ) - continue; - if ( !un->pkt->pkt.user_id->is_primary ) - continue; - /* We want the textual primary user ID here */ - if ( un->pkt->pkt.user_id->attrib_data ) - continue; + /* Get it before we print anything to avoid interrupting the + output with the "please do a --check-trustdb" line. */ + valid = get_validity (pk, un->pkt->pkt.user_id); - assert(pk); + keyid_str[17] = 0; /* cut off the "[uncertain]" part */ + write_status_text_and_buffer (statno, keyid_str, + un->pkt->pkt.user_id->name, + un->pkt->pkt.user_id->len, + -1); - /* Get it before we print anything to avoid interrupting - the output with the "please do a --check-trustdb" - line. */ - valid=get_validity(pk,un->pkt->pkt.user_id); + p = utf8_to_native (un->pkt->pkt.user_id->name, + un->pkt->pkt.user_id->len, 0); - keyid_str[17] = 0; /* cut off the "[uncertain]" part */ - write_status_text_and_buffer (statno, keyid_str, - un->pkt->pkt.user_id->name, - un->pkt->pkt.user_id->len, - -1 ); - - p=utf8_to_native(un->pkt->pkt.user_id->name, - un->pkt->pkt.user_id->len,0); - - if(rc) - log_info(_("BAD signature from \"%s\""),p); - else if(sig->flags.expired) - log_info(_("Expired signature from \"%s\""),p); - else - log_info(_("Good signature from \"%s\""),p); + if (rc) + log_info (_("BAD signature from \"%s\""), p); + else if (sig->flags.expired) + log_info (_("Expired signature from \"%s\""), p); + else + log_info (_("Good signature from \"%s\""), p); - xfree(p); + xfree(p); - if(opt.verify_options&VERIFY_SHOW_UID_VALIDITY) - log_printf (" [%s]\n",trust_value_to_string(valid)); - else - log_printf ("\n"); - count++; + if (opt.verify_options&VERIFY_SHOW_UID_VALIDITY) + log_printf (" [%s]\n",trust_value_to_string(valid)); + else + log_printf ("\n"); + count++; } - if( !count ) { /* just in case that we have no valid textual - userid */ - char *p; - /* Try for an invalid textual userid */ - for( un=keyblock; un; un = un->next ) { - if( un->pkt->pkttype == PKT_USER_ID && - !un->pkt->pkt.user_id->attrib_data ) - break; + if (!count) /* Just in case that we have no valid textual userid */ + { + char *p; + + /* Try for an invalid textual userid */ + for (un=keyblock; un; un = un->next) + { + if (un->pkt->pkttype == PKT_USER_ID + && !un->pkt->pkt.user_id->attrib_data) + break; } - /* Try for any userid at all */ - if(!un) { - for( un=keyblock; un; un = un->next ) { - if( un->pkt->pkttype == PKT_USER_ID ) - break; + /* Try for any userid at all */ + if (!un) + { + for (un=keyblock; un; un = un->next) + { + if (un->pkt->pkttype == PKT_USER_ID) + break; } } - if (opt.trust_model==TM_ALWAYS || !un) - keyid_str[17] = 0; /* cut off the "[uncertain]" part */ - - write_status_text_and_buffer (statno, keyid_str, - un? un->pkt->pkt.user_id->name:"[?]", - un? un->pkt->pkt.user_id->len:3, - -1 ); - - if(un) - p=utf8_to_native(un->pkt->pkt.user_id->name, - un->pkt->pkt.user_id->len,0); - else - p=xstrdup("[?]"); + if (opt.trust_model==TM_ALWAYS || !un) + keyid_str[17] = 0; /* cut off the "[uncertain]" part */ - if(rc) - log_info(_("BAD signature from \"%s\""),p); - else if(sig->flags.expired) - log_info(_("Expired signature from \"%s\""),p); - else - log_info(_("Good signature from \"%s\""),p); - if (opt.trust_model!=TM_ALWAYS && un) - log_printf (" %s",_("[uncertain]") ); - log_printf ("\n"); + write_status_text_and_buffer (statno, keyid_str, + un? un->pkt->pkt.user_id->name:"[?]", + un? un->pkt->pkt.user_id->len:3, + -1 ); + + if (un) + p= utf8_to_native (un->pkt->pkt.user_id->name, + un->pkt->pkt.user_id->len, 0); + else + p = xstrdup ("[?]"); + + if (rc) + log_info (_("BAD signature from \"%s\""), p); + else if (sig->flags.expired) + log_info (_("Expired signature from \"%s\""), p); + else + log_info (_("Good signature from \"%s\""), p); + if (opt.trust_model != TM_ALWAYS && un) + log_printf (" %s",_("[uncertain]") ); + log_printf ("\n"); } - /* If we have a good signature and already printed - * the primary user ID, print all the other user IDs */ - if ( count && !rc - && !(opt.verify_options&VERIFY_SHOW_PRIMARY_UID_ONLY)) { - char *p; - for( un=keyblock; un; un = un->next ) { - if( un->pkt->pkttype != PKT_USER_ID ) - continue; - if((un->pkt->pkt.user_id->is_revoked - || un->pkt->pkt.user_id->is_expired) - && !(opt.verify_options&VERIFY_SHOW_UNUSABLE_UIDS)) - continue; - /* Only skip textual primaries */ - if ( un->pkt->pkt.user_id->is_primary && - !un->pkt->pkt.user_id->attrib_data ) - continue; - - if(un->pkt->pkt.user_id->attrib_data) - { - dump_attribs (un->pkt->pkt.user_id, pk); + /* If we have a good signature and already printed + * the primary user ID, print all the other user IDs */ + if (count + && !rc + && !(opt.verify_options & VERIFY_SHOW_PRIMARY_UID_ONLY)) + { + char *p; + for( un=keyblock; un; un = un->next) + { + if (un->pkt->pkttype != PKT_USER_ID) + continue; + if ((un->pkt->pkt.user_id->is_revoked + || un->pkt->pkt.user_id->is_expired) + && !(opt.verify_options & VERIFY_SHOW_UNUSABLE_UIDS)) + continue; + /* Only skip textual primaries */ + if (un->pkt->pkt.user_id->is_primary + && !un->pkt->pkt.user_id->attrib_data ) + continue; - if(opt.verify_options&VERIFY_SHOW_PHOTOS) - show_photos(un->pkt->pkt.user_id->attribs, - un->pkt->pkt.user_id->numattribs, - pk ,un->pkt->pkt.user_id); - } + if (un->pkt->pkt.user_id->attrib_data) + { + dump_attribs (un->pkt->pkt.user_id, pk); - p=utf8_to_native(un->pkt->pkt.user_id->name, - un->pkt->pkt.user_id->len,0); - log_info(_(" aka \"%s\""),p); - xfree(p); + if (opt.verify_options&VERIFY_SHOW_PHOTOS) + show_photos (un->pkt->pkt.user_id->attribs, + un->pkt->pkt.user_id->numattribs, + pk ,un->pkt->pkt.user_id); + } - if(opt.verify_options&VERIFY_SHOW_UID_VALIDITY) - { - const char *valid; - if(un->pkt->pkt.user_id->is_revoked) - valid=_("revoked"); - else if(un->pkt->pkt.user_id->is_expired) - valid=_("expired"); - else - valid=trust_value_to_string(get_validity(pk, - un->pkt-> - pkt.user_id)); - log_printf (" [%s]\n",valid); - } - else - log_printf ("\n"); + p = utf8_to_native (un->pkt->pkt.user_id->name, + un->pkt->pkt.user_id->len, 0); + log_info (_(" aka \"%s\""), p); + xfree (p); + + if ((opt.verify_options & VERIFY_SHOW_UID_VALIDITY)) + { + const char *valid; + + if (un->pkt->pkt.user_id->is_revoked) + valid = _("revoked"); + else if (un->pkt->pkt.user_id->is_expired) + valid = _("expired"); + else + valid = (trust_value_to_string + (get_validity (pk, un->pkt->pkt.user_id))); + log_printf (" [%s]\n",valid); + } + else + log_printf ("\n"); } } - release_kbnode( keyblock ); + release_kbnode( keyblock ); - if( !rc ) - { - if(opt.verify_options&VERIFY_SHOW_POLICY_URLS) - show_policy_url(sig,0,1); - else - show_policy_url(sig,0,2); - - if(opt.verify_options&VERIFY_SHOW_KEYSERVER_URLS) - show_keyserver_url(sig,0,1); - else - show_keyserver_url(sig,0,2); + if (!rc) + { + if ((opt.verify_options & VERIFY_SHOW_POLICY_URLS)) + show_policy_url (sig, 0, 1); + else + show_policy_url (sig, 0, 2); + + if ((opt.verify_options & VERIFY_SHOW_KEYSERVER_URLS)) + show_keyserver_url (sig, 0, 1); + else + show_keyserver_url (sig, 0, 2); + + if ((opt.verify_options & VERIFY_SHOW_NOTATIONS)) + show_notation + (sig, 0, 1, + (((opt.verify_options&VERIFY_SHOW_STD_NOTATIONS)?1:0) + + ((opt.verify_options&VERIFY_SHOW_USER_NOTATIONS)?2:0))); + else + show_notation (sig, 0, 2, 0); + } - if(opt.verify_options&VERIFY_SHOW_NOTATIONS) - show_notation(sig,0,1, - ((opt.verify_options&VERIFY_SHOW_STD_NOTATIONS)?1:0)+ - ((opt.verify_options&VERIFY_SHOW_USER_NOTATIONS)?2:0)); - else - show_notation(sig,0,2,0); - } + if (!rc && is_status_enabled ()) + { + /* Print a status response with the fingerprint. */ + PKT_public_key *vpk = xmalloc_clear (sizeof *vpk); - if( !rc && is_status_enabled() ) { - /* print a status response with the fingerprint */ - PKT_public_key *vpk = xmalloc_clear( sizeof *vpk ); - - if( !get_pubkey( vpk, sig->keyid ) ) { - byte array[MAX_FINGERPRINT_LEN], *p; - char buf[MAX_FINGERPRINT_LEN*4+90], *bufp; - size_t i, n; - - bufp = buf; - fingerprint_from_pk( vpk, array, &n ); - p = array; - for(i=0; i < n ; i++, p++, bufp += 2) - sprintf(bufp, "%02X", *p ); - /* TODO: Replace the reserved '0' in the field below - with bits for status flags (policy url, notation, - etc.). Remember to make the buffer larger to - match! */ - sprintf(bufp, " %s %lu %lu %d 0 %d %d %02X ", - strtimestamp( sig->timestamp ), - (ulong)sig->timestamp,(ulong)sig->expiredate, - sig->version,sig->pubkey_algo,sig->digest_algo, - sig->sig_class); - bufp = bufp + strlen (bufp); - if (!vpk->flags.primary) { - u32 akid[2]; - - akid[0] = vpk->main_keyid[0]; - akid[1] = vpk->main_keyid[1]; - free_public_key (vpk); - vpk = xmalloc_clear( sizeof *vpk ); - if (get_pubkey (vpk, akid)) { - /* impossible error, we simply return a zeroed out fpr */ - n = MAX_FINGERPRINT_LEN < 20? MAX_FINGERPRINT_LEN : 20; - memset (array, 0, n); - } - else - fingerprint_from_pk( vpk, array, &n ); + if (!get_pubkey (vpk, sig->keyid)) + { + byte array[MAX_FINGERPRINT_LEN], *p; + char buf[MAX_FINGERPRINT_LEN*4+90], *bufp; + size_t i, n; + + bufp = buf; + fingerprint_from_pk (vpk, array, &n); + p = array; + for(i=0; i < n ; i++, p++, bufp += 2) + sprintf (bufp, "%02X", *p ); + /* TODO: Replace the reserved '0' in the field below + with bits for status flags (policy url, notation, + etc.). Remember to make the buffer larger to match! */ + sprintf (bufp, " %s %lu %lu %d 0 %d %d %02X ", + strtimestamp( sig->timestamp ), + (ulong)sig->timestamp,(ulong)sig->expiredate, + sig->version,sig->pubkey_algo,sig->digest_algo, + sig->sig_class); + bufp = bufp + strlen (bufp); + if (!vpk->flags.primary) + { + u32 akid[2]; + + akid[0] = vpk->main_keyid[0]; + akid[1] = vpk->main_keyid[1]; + free_public_key (vpk); + vpk = xmalloc_clear (sizeof *vpk); + if (get_pubkey (vpk, akid)) + { + /* Impossible error, we simply return a zeroed out fpr */ + n = MAX_FINGERPRINT_LEN < 20? MAX_FINGERPRINT_LEN : 20; + memset (array, 0, n); + } + else + fingerprint_from_pk( vpk, array, &n ); } - p = array; - for(i=0; i < n ; i++, p++, bufp += 2) - sprintf(bufp, "%02X", *p ); - write_status_text( STATUS_VALIDSIG, buf ); + p = array; + for (i=0; i < n ; i++, p++, bufp += 2) + sprintf(bufp, "%02X", *p ); + write_status_text (STATUS_VALIDSIG, buf); } - free_public_key( vpk ); + free_public_key (vpk); } - if (!rc) - { - if(opt.verify_options&VERIFY_PKA_LOOKUPS) - pka_uri_from_sig (sig); /* Make sure PKA info is available. */ - rc = check_signatures_trust( sig ); - } + if (!rc) + { + if ((opt.verify_options & VERIFY_PKA_LOOKUPS)) + pka_uri_from_sig (sig); /* Make sure PKA info is available. */ + rc = check_signatures_trust (sig); + } - if(sig->flags.expired) - { - log_info(_("Signature expired %s\n"), - asctimestamp(sig->expiredate)); - rc=G10ERR_GENERAL; /* need a better error here? */ - } - else if(sig->expiredate) - log_info(_("Signature expires %s\n"),asctimestamp(sig->expiredate)); - - if(opt.verbose) - log_info(_("%s signature, digest algorithm %s\n"), - sig->sig_class==0x00?_("binary"): - sig->sig_class==0x01?_("textmode"):_("unknown"), - gcry_md_algo_name (sig->digest_algo)); - - if( rc ) - g10_errors_seen = 1; - if( opt.batch && rc ) - g10_exit(1); + if (sig->flags.expired) + { + log_info (_("Signature expired %s\n"), asctimestamp(sig->expiredate)); + rc = G10ERR_GENERAL; /* need a better error here? */ + } + else if (sig->expiredate) + log_info (_("Signature expires %s\n"), asctimestamp(sig->expiredate)); + + if (opt.verbose) + log_info (_("%s signature, digest algorithm %s\n"), + sig->sig_class==0x00?_("binary"): + sig->sig_class==0x01?_("textmode"):_("unknown"), + gcry_md_algo_name (sig->digest_algo)); + + if (rc) + g10_errors_seen = 1; + if (opt.batch && rc) + g10_exit (1); } - else { - char buf[50]; - sprintf(buf, "%08lX%08lX %d %d %02x %lu %d", - (ulong)sig->keyid[0], (ulong)sig->keyid[1], - sig->pubkey_algo, sig->digest_algo, - sig->sig_class, (ulong)sig->timestamp, rc ); - write_status_text( STATUS_ERRSIG, buf ); - if( rc == G10ERR_NO_PUBKEY ) { - buf[16] = 0; - write_status_text( STATUS_NO_PUBKEY, buf ); + else + { + char buf[50]; + + snprintf (buf, sizeof buf, "%08lX%08lX %d %d %02x %lu %d", + (ulong)sig->keyid[0], (ulong)sig->keyid[1], + sig->pubkey_algo, sig->digest_algo, + sig->sig_class, (ulong)sig->timestamp, rc); + write_status_text (STATUS_ERRSIG, buf); + if (gpg_err_code (rc) == G10ERR_NO_PUBKEY) + { + buf[16] = 0; + write_status_text (STATUS_NO_PUBKEY, buf); } - if( rc != G10ERR_NOT_PROCESSED ) - log_error(_("Can't check signature: %s\n"), g10_errstr(rc) ); + if (gpg_err_code (rc) != G10ERR_NOT_PROCESSED) + log_error (_("Can't check signature: %s\n"), g10_errstr(rc)); } - return rc; + + return rc; } commit 09055aa0f7993aaf4dcffdd80d8192945ae6080a Author: Werner Koch Date: Wed May 7 13:39:28 2014 +0200 gpg: Mark experimental algorithms in the key listing. * g10/keylist.c (list_keyblock_print): Remove duplicate curve name. Print a note for experimental algorithms. * g10/misc.c (print_pubkey_algo_note): Fix warning message. diff --git a/g10/keylist.c b/g10/keylist.c index 71f72e2..1ecfce9 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -1,6 +1,7 @@ /* keylist.c - Print information about OpenPGP keys * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, * 2008, 2010, 2012 Free Software Foundation, Inc. + * Copyright (C) 2013, 2014 Werner Koch * * This file is part of GnuPG. * @@ -822,18 +823,6 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque) pubkey_string (pk, pkstrbuf, sizeof pkstrbuf), keystr_from_pk (pk), datestr_from_pk (pk)); - if (pk->pubkey_algo == PUBKEY_ALGO_ECDSA - || pk->pubkey_algo == PUBKEY_ALGO_EDDSA - || pk->pubkey_algo == PUBKEY_ALGO_ECDH) - { - char *curve = openpgp_oid_to_str (pk->pkey[0]); - const char *name = openpgp_oid_to_curve (curve); - if (!*name || *name == '?') - name = curve; - es_fprintf (es_stdout, " %s", name); - xfree (curve); - } - if (pk->flags.revoked) { es_fprintf (es_stdout, " ["); @@ -863,6 +852,9 @@ list_keyblock_print (KBNODE keyblock, int secret, int fpr, void *opaque) } #endif + if (pk->pubkey_algo >= 100) + es_fprintf (es_stdout, " [experimental algorithm %d]", pk->pubkey_algo); + es_fprintf (es_stdout, "\n"); if (fpr) diff --git a/g10/misc.c b/g10/misc.c index 77928aa..54ddad2 100644 --- a/g10/misc.c +++ b/g10/misc.c @@ -299,10 +299,10 @@ print_pubkey_algo_note (pubkey_algo_t algo) { warn=1; log_info (_("WARNING: using experimental public key algorithm %s\n"), - openpgp_cipher_algo_name (algo)); + openpgp_pk_algo_name (algo)); } } - else if (algo == 20) + else if (algo == PUBKEY_ALGO_ELGAMAL) { log_info (_("WARNING: Elgamal sign+encrypt keys are deprecated\n")); } commit 8fee6c1ce6d116fe7909dbe1184d95bc91305484 Author: Werner Koch Date: Wed May 7 13:16:32 2014 +0200 gpg: Finish experimental support for Ed25519. * agent/cvt-openpgp.c (try_do_unprotect_arg_s): Add field "curve". (get_keygrip): Add and use arg CURVE. (convert_secret_key): Ditto. (convert_transfer_key): Ditto. (get_npkey_nskey): New. (prepare_unprotect): Replace gcrypt functions by get_npkey_nskey. Allow opaque MPIs. (do_unprotect): Use CURVE instead of parameters. (convert_from_openpgp_main): Ditto. (convert_to_openpgp): Simplify. * g10/import.c (one_mpi_from_pkey): Remove. (transfer_secret_keys): Rewrite to use the curve instead of the parameters. * g10/parse-packet.c (parse_key): Mark protected MPIs with USER1 flag. * common/openpgp-oid.c (openpgp_curve_to_oid): Allow the use of "NIST P-256" et al. * g10/keygen.c (ask_curve): Add arg ALGO. (generate_keypair): Rewrite the ECC key logic. * tests/openpgp/ecc.test: Provide the "ecc" passphrase. diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c index ef34463..28f0380 100644 --- a/agent/cvt-openpgp.c +++ b/agent/cvt-openpgp.c @@ -36,6 +36,7 @@ struct try_do_unprotect_arg_s int is_v4; int is_protected; int pubkey_algo; + const char *curve; int protect_algo; char *iv; int ivlen; @@ -54,7 +55,8 @@ struct try_do_unprotect_arg_s /* Compute the keygrip from the public key and store it at GRIP. */ static gpg_error_t -get_keygrip (int pubkey_algo, gcry_mpi_t *pkey, unsigned char *grip) +get_keygrip (int pubkey_algo, const char *curve, gcry_mpi_t *pkey, + unsigned char *grip) { gpg_error_t err; gcry_sexp_t s_pkey = NULL; @@ -80,9 +82,8 @@ get_keygrip (int pubkey_algo, gcry_mpi_t *pkey, unsigned char *grip) case GCRY_PK_ECC: err = gcry_sexp_build (&s_pkey, NULL, - "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))", - pkey[0], pkey[1], pkey[2], pkey[3], pkey[4], - pkey[5]); + "(public-key(ecc(curve %s)(q%m)))", + curve, pkey[0]); break; default: @@ -102,7 +103,8 @@ get_keygrip (int pubkey_algo, gcry_mpi_t *pkey, unsigned char *grip) parameters into our s-expression based format. Note that PUBKEY_ALGO has an gcrypt algorithm number. */ static gpg_error_t -convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey) +convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey, + const char *curve) { gpg_error_t err; gcry_sexp_t s_skey = NULL; @@ -135,11 +137,12 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey) break; case GCRY_PK_ECC: - err = gcry_sexp_build (&s_skey, NULL, - "(private-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)" - "(d%m)))", - skey[0], skey[1], skey[2], skey[3], skey[4], - skey[5], skey[6]); + if (!curve) + err = gpg_error (GPG_ERR_BAD_SECKEY); + else + err = gcry_sexp_build (&s_skey, NULL, + "(private-key(ecc(curve%s)(q%m)(d%m)))", + curve, skey[0], skey[1]); break; default: @@ -160,7 +163,7 @@ convert_secret_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey) mode. Note that PUBKEY_ALGO has an gcrypt algorithm number. */ static gpg_error_t convert_transfer_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey, - gcry_sexp_t transfer_key) + const char *curve, gcry_sexp_t transfer_key) { gpg_error_t err; gcry_sexp_t s_skey = NULL; @@ -197,9 +200,9 @@ convert_transfer_key (gcry_sexp_t *r_key, int pubkey_algo, gcry_mpi_t *skey, case GCRY_PK_ECC: err = gcry_sexp_build (&s_skey, NULL, - "(protected-private-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)" + "(protected-private-key(ecc(curve%s)(q%m)" "(protected openpgp-native%S)))", - skey[0], skey[1], skey[2], skey[3], skey[4], skey[5], transfer_key); + curve, skey[0], transfer_key); break; default: @@ -254,6 +257,22 @@ checksum (const unsigned char *p, unsigned int n) } +/* Return the number of expected key parameters. */ +static void +get_npkey_nskey (int pubkey_algo, size_t *npkey, size_t *nskey) +{ + switch (pubkey_algo) + { + case GCRY_PK_RSA: *npkey = 2; *nskey = 6; break; + case GCRY_PK_ELG: *npkey = 3; *nskey = 4; break; + case GCRY_PK_ELG_E: *npkey = 3; *nskey = 4; break; + case GCRY_PK_DSA: *npkey = 4; *nskey = 5; break; + case GCRY_PK_ECC: *npkey = 1; *nskey = 2; break; + default: *npkey = 0; *nskey = 0; break; + } +} + + /* Helper for do_unprotect. PUBKEY_ALOGO is the gcrypt algo number. On success R_NPKEY and R_NSKEY receive the number or parameters for the algorithm PUBKEY_ALGO and R_SKEYLEN the used length of @@ -264,7 +283,6 @@ prepare_unprotect (int pubkey_algo, gcry_mpi_t *skey, size_t skeysize, unsigned int *r_npkey, unsigned int *r_nskey, unsigned int *r_skeylen) { - gpg_error_t err; size_t npkey, nskey, skeylen; int i; @@ -293,12 +311,8 @@ prepare_unprotect (int pubkey_algo, gcry_mpi_t *skey, size_t skeysize, /* Get properties of the public key algorithm and do some consistency checks. Note that we need at least NPKEY+1 elements in the SKEY array. */ - if ( (err = gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NPKEY, - NULL, &npkey)) - || (err = gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NSKEY, - NULL, &nskey))) - return err; - if (!npkey || npkey >= nskey) + get_npkey_nskey (pubkey_algo, &npkey, &nskey); + if (!npkey || !nskey || npkey >= nskey) return gpg_error (GPG_ERR_INTERNAL); if (skeylen <= npkey) return gpg_error (GPG_ERR_MISSING_VALUE); @@ -309,7 +323,7 @@ prepare_unprotect (int pubkey_algo, gcry_mpi_t *skey, size_t skeysize, encrypted. */ for (i=0; i < npkey; i++) { - if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_OPAQUE)) + if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1)) return gpg_error (GPG_ERR_BAD_SECKEY); } @@ -329,7 +343,7 @@ prepare_unprotect (int pubkey_algo, gcry_mpi_t *skey, size_t skeysize, static int do_unprotect (const char *passphrase, int pkt_version, int pubkey_algo, int is_protected, - gcry_mpi_t *skey, size_t skeysize, + const char *curve, gcry_mpi_t *skey, size_t skeysize, int protect_algo, void *protect_iv, size_t protect_ivlen, int s2k_mode, int s2k_algo, byte *s2k_salt, u32 s2k_count, u16 desired_csum, gcry_sexp_t *r_key) @@ -353,23 +367,26 @@ do_unprotect (const char *passphrase, merely verify the checksum. */ if (!is_protected) { - unsigned char *buffer; - actual_csum = 0; for (i=npkey; i < nskey; i++) { - if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_OPAQUE)) + if (!skey[i] || gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1)) return gpg_error (GPG_ERR_BAD_SECKEY); - err = gcry_mpi_print (GCRYMPI_FMT_PGP, NULL, 0, &nbytes, skey[i]); - if (!err) + if (gcry_mpi_get_flag (skey[i], GCRYMPI_FLAG_USER1)) + { + unsigned int nbits; + const unsigned char *buffer; + buffer = gcry_mpi_get_opaque (skey[i], &nbits); + nbytes = (nbits+7)/8; + actual_csum += checksum (buffer, nbytes); + } + else { - buffer = (gcry_is_secure (skey[i])? - xtrymalloc_secure (nbytes) : xtrymalloc (nbytes)); - if (!buffer) - return gpg_error_from_syserror (); - err = gcry_mpi_print (GCRYMPI_FMT_PGP, buffer, nbytes, - NULL, skey[i]); + unsigned char *buffer; + + err = gcry_mpi_aprint (GCRYMPI_FMT_PGP, &buffer, &nbytes, + skey[i]); if (!err) actual_csum += checksum (buffer, nbytes); xfree (buffer); @@ -428,7 +445,8 @@ do_unprotect (const char *passphrase, { int ndata; unsigned int ndatabits; - unsigned char *p, *data; + const unsigned char *p; + unsigned char *data; u16 csum_pgp7 = 0; if (!gcry_mpi_get_flag (skey[npkey], GCRYMPI_FLAG_OPAQUE )) @@ -527,7 +545,7 @@ do_unprotect (const char *passphrase, for (i = npkey; i < nskey; i++) { - unsigned char *p; + const unsigned char *p; size_t ndata; unsigned int ndatabits; @@ -580,7 +598,7 @@ do_unprotect (const char *passphrase, if (nskey != skeylen) err = gpg_error (GPG_ERR_BAD_SECKEY); else - err = convert_secret_key (r_key, pubkey_algo, skey); + err = convert_secret_key (r_key, pubkey_algo, skey, curve); if (err) return err; @@ -608,6 +626,7 @@ try_do_unprotect_cb (struct pin_entry_info_s *pi) err = do_unprotect (pi->pin, arg->is_v4? 4:3, arg->pubkey_algo, arg->is_protected, + arg->curve, arg->skey, arg->skeysize, arg->protect_algo, arg->iv, arg->ivlen, arg->s2k_mode, arg->s2k_algo, @@ -651,6 +670,7 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp, u32 s2k_count = 0; size_t npkey, nskey; gcry_mpi_t skey[10]; /* We support up to 9 parameters. */ + char *curve = NULL; u16 desired_csum; int skeyidx = 0; gcry_sexp_t s_skey = NULL; @@ -695,8 +715,6 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp, if (!string) goto bad_seckey; protect_algo = gcry_cipher_map_name (string); - if (!protect_algo && !!strcmp (string, "IDEA")) - protect_algo = GCRY_CIPHER_IDEA; xfree (string); value = gcry_sexp_nth_data (list, 3, &valuelen); @@ -739,11 +757,21 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp, pubkey_algo = gcry_pk_map_name (string); xfree (string); - if (gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NPKEY, NULL, &npkey) - || gcry_pk_algo_info (pubkey_algo, GCRYCTL_GET_ALGO_NSKEY, NULL, &nskey) - || !npkey || npkey >= nskey) + get_npkey_nskey (pubkey_algo, &npkey, &nskey); + if (!npkey || !nskey || npkey >= nskey) goto bad_seckey; + if (npkey == 1) /* This is ECC */ + { + gcry_sexp_release (list); + list = gcry_sexp_find_token (top_list, "curve", 0); + if (!list) + goto bad_seckey; + curve = gcry_sexp_nth_string (list, 1); + if (!curve) + goto bad_seckey; + } + gcry_sexp_release (list); list = gcry_sexp_find_token (top_list, "skey", 0); if (!list) @@ -770,15 +798,15 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp, value = gcry_sexp_nth_data (list, ++idx, &valuelen); if (!value || !valuelen) goto bad_seckey; - if (is_enc) + if (is_enc || curve) { - void *p = xtrymalloc (valuelen); - if (!p) - goto outofmem; - memcpy (p, value, valuelen); - skey[skeyidx] = gcry_mpi_set_opaque (NULL, p, valuelen*8); + /* Encrypted parameters and ECC parameters need or can be + stored as opaque. */ + skey[skeyidx] = gcry_mpi_set_opaque_copy (NULL, value, valuelen*8); if (!skey[skeyidx]) goto outofmem; + if (is_enc) + gcry_mpi_set_flag (skey[skeyidx], GCRYMPI_FLAG_USER1); } else { @@ -807,33 +835,24 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp, gcry_sexp_release (list); list = NULL; gcry_sexp_release (top_list); top_list = NULL; - /* log_debug ("XXX is_v4=%d\n", is_v4); */ - /* log_debug ("XXX pubkey_algo=%d\n", pubkey_algo); */ - /* log_debug ("XXX is_protected=%d\n", is_protected); */ - /* log_debug ("XXX protect_algo=%d\n", protect_algo); */ - /* log_printhex ("XXX iv", iv, ivlen); */ - /* log_debug ("XXX ivlen=%d\n", ivlen); */ - /* log_debug ("XXX s2k_mode=%d\n", s2k_mode); */ - /* log_debug ("XXX s2k_algo=%d\n", s2k_algo); */ - /* log_printhex ("XXX s2k_salt", s2k_salt, sizeof s2k_salt); */ - /* log_debug ("XXX s2k_count=%lu\n", (unsigned long)s2k_count); */ - /* for (idx=0; skey[idx]; idx++) */ - /* { */ - /* int is_enc = gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_OPAQUE); */ - /* log_info ("XXX skey[%d]%s:", idx, is_enc? " (enc)":""); */ - /* if (is_enc) */ - /* { */ - /* void *p; */ - /* unsigned int nbits; */ - /* p = gcry_mpi_get_opaque (skey[idx], &nbits); */ - /* log_printhex (NULL, p, (nbits+7)/8); */ - /* } */ - /* else */ - /* gcry_mpi_dump (skey[idx]); */ - /* log_printf ("\n"); */ - /* } */ - - err = get_keygrip (pubkey_algo, skey, grip); +#if 0 + log_debug ("XXX is_v4=%d\n", is_v4); + log_debug ("XXX pubkey_algo=%d\n", pubkey_algo); + log_debug ("XXX is_protected=%d\n", is_protected); + log_debug ("XXX protect_algo=%d\n", protect_algo); + log_printhex ("XXX iv", iv, ivlen); + log_debug ("XXX ivlen=%d\n", ivlen); + log_debug ("XXX s2k_mode=%d\n", s2k_mode); + log_debug ("XXX s2k_algo=%d\n", s2k_algo); + log_printhex ("XXX s2k_salt", s2k_salt, sizeof s2k_salt); + log_debug ("XXX s2k_count=%lu\n", (unsigned long)s2k_count); + log_debug ("XXX curve='%s'\n", curve); + for (idx=0; skey[idx]; idx++) + gcry_log_debugmpi (gcry_mpi_get_flag (skey[idx], GCRYMPI_FLAG_USER1) + ? "skey(e)" : "skey(_)", skey[idx]); +#endif /*0*/ + + err = get_keygrip (pubkey_algo, curve, skey, grip); if (err) goto leave; @@ -850,7 +869,7 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp, if (err) goto leave; - err = convert_transfer_key (&s_skey, pubkey_algo, skey, s_pgp); + err = convert_transfer_key (&s_skey, pubkey_algo, skey, curve, s_pgp); if (err) goto leave; } @@ -871,6 +890,7 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp, pi_arg.is_v4 = is_v4; pi_arg.is_protected = is_protected; pi_arg.pubkey_algo = pubkey_algo; + pi_arg.curve = curve; pi_arg.protect_algo = protect_algo; pi_arg.iv = iv; pi_arg.ivlen = ivlen; @@ -929,6 +949,7 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp, err = make_canon_sexp_pad (s_skey, 1, r_key, NULL); leave: + xfree (curve); gcry_sexp_release (s_skey); gcry_sexp_release (list); gcry_sexp_release (top_list); @@ -1223,11 +1244,9 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, { char countbuf[35]; membuf_t mbuf; - void *format_args_buf_ptr[1]; - int format_args_buf_int[1]; void *format_args[10+2]; - unsigned int n; - gcry_sexp_t tmpkey, tmpsexp = NULL; + gcry_sexp_t tmpkey; + gcry_sexp_t tmpsexp = NULL; snprintf (countbuf, sizeof countbuf, "%lu", s2k_count); @@ -1238,11 +1257,8 @@ convert_to_openpgp (ctrl_t ctrl, gcry_sexp_t s_key, const char *passphrase, put_membuf_str (&mbuf, " _ %m"); format_args[j++] = array + i; } - put_membuf_str (&mbuf, " e %b"); - format_args_buf_ptr[0] = gcry_mpi_get_opaque (array[npkey], &n); - format_args_buf_int[0] = (n+7)/8; - format_args[j++] = format_args_buf_int; - format_args[j++] = format_args_buf_ptr; + put_membuf_str (&mbuf, " e %m"); + format_args[j++] = array + npkey; put_membuf_str (&mbuf, ")\n"); put_membuf (&mbuf, "", 1); diff --git a/agent/keyformat.txt b/agent/keyformat.txt index 3f95dae..42c4b1f 100644 --- a/agent/keyformat.txt +++ b/agent/keyformat.txt @@ -211,6 +211,7 @@ This format is used to transfer keys between gpg and gpg-agent. (openpgp-private-key (version V) (algo PUBKEYALGO) + (curve CURVENAME) (skey _ P1 _ P2 _ P3 ... e PN) (csum n) (protection PROTTYPE PROTALGO IV S2KMODE S2KHASH S2KSALT S2KCOUNT)) @@ -218,6 +219,7 @@ This format is used to transfer keys between gpg and gpg-agent. * V is the packet version number (3 or 4). * PUBKEYALGO is a Libgcrypt algo name +* CURVENAME is the name of the curve - only used with ECC. * P1 .. PN are the parameters; the public parameters are never encrypted the secrect key parameters are encrypted if the "protection" list is given. To make this more explicit each parameter is preceded by a diff --git a/common/openpgp-oid.c b/common/openpgp-oid.c index 94a2296..bcb9885 100644 --- a/common/openpgp-oid.c +++ b/common/openpgp-oid.c @@ -280,17 +280,20 @@ openpgp_curve_to_oid (const char *name, unsigned int *r_nbits) oidstr = "1.3.6.1.4.1.11591.15.1"; nbits = 255; } - else if (!strcmp (name, "nistp256")) + else if (!strcmp (name, "nistp256") || !strcmp (name, "NIST P-256")) { + /* Libgcrypt uses "NIST P-256" as standard name for this curve + and thus the key generation returns this value. Thus we + allow both strings. */ oidstr = "1.2.840.10045.3.1.7"; nbits = 256; } - else if (!strcmp (name, "nistp384")) + else if (!strcmp (name, "nistp384") || !strcmp (name, "NIST P-384")) { oidstr = "1.3.132.0.34"; nbits = 384; } - else if (!strcmp (name, "nistp521")) + else if (!strcmp (name, "nistp521") || !strcmp (name, "NIST P-521")) { oidstr = "1.3.132.0.35"; nbits = 521; diff --git a/g10/import.c b/g10/import.c index 8223041..2b219a2 100644 --- a/g10/import.c +++ b/g10/import.c @@ -1128,37 +1128,6 @@ import_one (ctrl_t ctrl, } -/* Extract one MPI value from the S-expression PKEY which is expected - to hold a "public-key". Returns NULL on error. */ -static gcry_mpi_t -one_mpi_from_pkey (gcry_sexp_t pkey, const char *name, size_t namelen) -{ - gcry_sexp_t list, l2; - gcry_mpi_t a; - - list = gcry_sexp_find_token (pkey, "public-key", 0); - if (!list) - return NULL; - l2 = gcry_sexp_cadr (list); - gcry_sexp_release (list); - list = l2; - if (!list) - return NULL; - - l2 = gcry_sexp_find_token (list, name, namelen); - if (!l2) - { - gcry_sexp_release (list); - return NULL; - } - a = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); - gcry_sexp_release (l2); - gcry_sexp_release (list); - - return a; -} - - /* Transfer all the secret keys in SEC_KEYBLOCK to the gpg-agent. The function prints diagnostics and returns an error code. */ static gpg_error_t @@ -1174,18 +1143,15 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock) int nskey; membuf_t mbuf; int i, j; - unsigned int n; - void *format_args_buf_ptr[PUBKEY_MAX_NSKEY]; - int format_args_buf_int[PUBKEY_MAX_NSKEY]; void *format_args[2*PUBKEY_MAX_NSKEY]; gcry_sexp_t skey, prot, tmpsexp; + gcry_sexp_t curve = NULL; unsigned char *transferkey = NULL; size_t transferkeylen; gcry_cipher_hd_t cipherhd = NULL; unsigned char *wrappedkey = NULL; size_t wrappedkeylen; char *cache_nonce = NULL; - gcry_mpi_t ecc_params[5] = {NULL, NULL, NULL, NULL, NULL}; /* Get the current KEK. */ err = agent_keywrap_key (ctrl, 0, &kek, &keklen); @@ -1263,65 +1229,30 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock) || pk->pubkey_algo == PUBKEY_ALGO_EDDSA || pk->pubkey_algo == PUBKEY_ALGO_ECDH) { - /* We need special treatment for ECC algorithms. OpenPGP - stores only the curve name but the agent expects a full - key. This is so that we can keep all curve name - validation code out of gpg-agent. */ -#if PUBKEY_MAX_NSKEY < 7 -#error PUBKEY_MAX_NSKEY too low for ECC -#endif - char *curve = openpgp_oid_to_str (pk->pkey[0]); - if (!curve) + /* The ECC case. */ + char *curvestr = openpgp_oid_to_str (pk->pkey[0]); + if (!curvestr) err = gpg_error_from_syserror (); else { - gcry_sexp_t cparam = gcry_pk_get_param (GCRY_PK_ECC, curve); - - xfree (curve); - if (!cparam) - err = gpg_error (GPG_ERR_UNKNOWN_CURVE); - else + err = gcry_sexp_build (&curve, NULL, "(curve %s)", curvestr); + xfree (curvestr); + if (!err) { - const char *s; - - /* Append the curve parameters P, A, B, G and N. */ - for (i=j=0; !err && *(s = "pabgn"+i); i++) - { - ecc_params[i] = one_mpi_from_pkey (cparam, s, 1); - if (!ecc_params[i]) - err = gpg_error (GPG_ERR_INV_CURVE); - else - { - put_membuf_str (&mbuf, " _ %m"); - format_args[j++] = ecc_params+i; - } - } - gcry_sexp_release (cparam); - if (!err) - { - /* Append the public key element Q. */ - put_membuf_str (&mbuf, " _ %m"); - format_args[j++] = pk->pkey + 1; - - /* Append the secret key element D. Note that - for ECDH we need to skip PKEY[2] because this - holds the KEK which is not needed. */ - i = pk->pubkey_algo == PUBKEY_ALGO_ECDH? 3 : 2; - if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE)) - { - put_membuf_str (&mbuf, " e %b"); - format_args_buf_ptr[i] - = gcry_mpi_get_opaque (pk->pkey[i],&n); - format_args_buf_int[i] = (n+7)/8; - format_args[j++] = format_args_buf_int + i; - format_args[j++] = format_args_buf_ptr + i; - } - else - { - put_membuf_str (&mbuf, " _ %m"); - format_args[j++] = pk->pkey + i; - } - } + j = 0; + /* Append the public key element Q. */ + put_membuf_str (&mbuf, " _ %m"); + format_args[j++] = pk->pkey + 1; + + /* Append the secret key element D. For ECDH we + skip PKEY[2] because this holds the KEK which is + not needed by gpg-agent. */ + i = pk->pubkey_algo == PUBKEY_ALGO_ECDH? 3 : 2; + if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_USER1)) + put_membuf_str (&mbuf, " e %m"); + else + put_membuf_str (&mbuf, " _ %m"); + format_args[j++] = pk->pkey + i; } } } @@ -1331,23 +1262,16 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock) for (i=j=0; i < nskey; i++) { if (!pk->pkey[i]) - ; /* Protected keys only have NPKEY+1 elements. */ - else if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_OPAQUE)) - { - put_membuf_str (&mbuf, " e %b"); - format_args_buf_ptr[i] = gcry_mpi_get_opaque (pk->pkey[i],&n); - format_args_buf_int[i] = (n+7)/8; - format_args[j++] = format_args_buf_int + i; - format_args[j++] = format_args_buf_ptr + i; - } + continue; /* Protected keys only have NPKEY+1 elements. */ + + if (gcry_mpi_get_flag (pk->pkey[i], GCRYMPI_FLAG_USER1)) + put_membuf_str (&mbuf, " e %m"); else - { - put_membuf_str (&mbuf, " _ %m"); - format_args[j++] = pk->pkey + i; - } + put_membuf_str (&mbuf, " _ %m"); + format_args[j++] = pk->pkey + i; } } - put_membuf_str (&mbuf, ")\n"); + put_membuf_str (&mbuf, ")"); put_membuf (&mbuf, "", 1); if (err) xfree (get_membuf (&mbuf, NULL)); @@ -1398,12 +1322,13 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock) "(openpgp-private-key\n" " (version %d)\n" " (algo %s)\n" - " %S\n" + " %S%S\n" " (csum %d)\n" " %S)\n", pk->version, openpgp_pk_algo_name (pk->pubkey_algo), - skey, (int)(unsigned long)ski->csum, prot); + curve, skey, + (int)(unsigned long)ski->csum, prot); gcry_sexp_release (skey); gcry_sexp_release (prot); if (!err) @@ -1463,8 +1388,7 @@ transfer_secret_keys (ctrl_t ctrl, struct stats_s *stats, kbnode_t sec_keyblock) } leave: - for (i=0; i < DIM (ecc_params); i++) - gcry_mpi_release (ecc_params[i]); + gcry_sexp_release (curve); xfree (cache_nonce); xfree (wrappedkey); xfree (transferkey); diff --git a/g10/keygen.c b/g10/keygen.c index f3052e4..314cf9b 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -2086,29 +2086,30 @@ ask_keysize (int algo, unsigned int primary_keysize) } -/* Ask for the key size. ALGO is the algorithm. If PRIMARY_KEYSIZE - is not 0, the function asks for the size of the encryption - subkey. */ +/* Ask for the curve. ALGO is the selected algorithm which this + function may adjust. Returns a malloced string with the name of + the curve. */ static char * -ask_curve (void) +ask_curve (int *algo) { struct { const char *name; int available; int expert_only; + int fix_curve; const char *pretty_name; } curves[] = { #if GPG_USE_EDDSA - { "Ed25519", 0, 0, "Curve 25519" }, + { "Curve25519", 0, 0, 1, "Curve 25519" }, #endif #if GPG_USE_ECDSA || GPG_USE_ECDH - { "NIST P-256", 0, 1, }, - { "NIST P-384", 0, 0, }, - { "NIST P-521", 0, 1, }, - { "brainpoolP256r1", 0, 1, "Brainpool P-256" }, - { "brainpoolP384r1", 0, 1, "Brainpool P-384" }, - { "brainpoolP512r1", 0, 1, "Brainpool P-512" }, - { "secp256k1", 0, 1 }, + { "NIST P-256", 0, 1, 0, }, + { "NIST P-384", 0, 0, 0, }, + { "NIST P-521", 0, 1, 0, }, + { "brainpoolP256r1", 0, 1, 0, "Brainpool P-256" }, + { "brainpoolP384r1", 0, 1, 0, "Brainpool P-384" }, + { "brainpoolP512r1", 0, 1, 0, "Brainpool P-512" }, + { "secp256k1", 0, 1, 0 }, #endif }; int idx; @@ -2127,9 +2128,14 @@ ask_curve (void) if (!opt.expert && curves[idx].expert_only) continue; + /* FIXME: The strcmp below is a temporary hack during + development. It shall be removed as soon as we have proper + Curve25519 support in Libgcrypt. */ gcry_sexp_release (keyparms); rc = gcry_sexp_build (&keyparms, NULL, - "(public-key(ecc(curve %s)))", curves[idx].name); + "(public-key(ecc(curve %s)))", + (!strcmp (curves[idx].name, "Curve25519") + ? "Ed25519" : curves[idx].name)); if (rc) continue; if (!gcry_pk_get_curve (keyparms, 0, NULL)) @@ -2171,7 +2177,22 @@ ask_curve (void) tty_printf (_("Invalid selection.\n")); else { - result = xstrdup (curves[idx].name); + if (curves[idx].fix_curve) + log_info ("WARNING: Curve25519 is an experimental algorithm and" + " not yet specified by OpenPGP. The current" + " implementation may change with the next GnuPG release" + " and thus rendering the key unusable!\n"); + + /* If the user selected a signing algorithm and Curve25519 + we need to update the algo and and the curve name. */ + if ((*algo == PUBKEY_ALGO_ECDSA || *algo == PUBKEY_ALGO_EDDSA) + && curves[idx].fix_curve) + { + *algo = PUBKEY_ALGO_EDDSA; + result = xstrdup ("Ed25519"); + } + else + result = xstrdup (curves[idx].name); break; } } @@ -3459,16 +3480,16 @@ generate_keypair (ctrl_t ctrl, const char *fname, const char *card_serialno, { /* Create primary and subkey at once. */ both = 1; - r = xmalloc_clear( sizeof *r + 20 ); - r->key = pKEYTYPE; - sprintf( r->u.value, "%d", algo ); - r->next = para; - para = r; if (algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_EDDSA || algo == PUBKEY_ALGO_ECDH) { - curve = ask_curve (); + curve = ask_curve (&algo); + r = xmalloc_clear( sizeof *r + 20 ); + r->key = pKEYTYPE; + sprintf( r->u.value, "%d", algo); + r->next = para; + para = r; nbits = 0; r = xmalloc_clear (sizeof *r + strlen (curve)); r->key = pKEYCURVE; @@ -3478,6 +3499,11 @@ generate_keypair (ctrl_t ctrl, const char *fname, const char *card_serialno, } else { + r = xmalloc_clear( sizeof *r + 20 ); + r->key = pKEYTYPE; + sprintf( r->u.value, "%d", algo); + r->next = para; + para = r; nbits = ask_keysize (algo, 0); r = xmalloc_clear( sizeof *r + 20 ); r->key = pKEYLENGTH; @@ -3501,9 +3527,43 @@ generate_keypair (ctrl_t ctrl, const char *fname, const char *card_serialno, strcpy( r->u.value, "encrypt" ); r->next = para; para = r; + + if (algo == PUBKEY_ALGO_ECDSA + || algo == PUBKEY_ALGO_EDDSA + || algo == PUBKEY_ALGO_ECDH) + { + if (algo == PUBKEY_ALGO_EDDSA + && subkey_algo == PUBKEY_ALGO_ECDH) + { + /* Need to switch to a different curve for the + encryption key. */ + xfree (curve); + curve = xstrdup ("Curve25519"); + } + r = xmalloc_clear (sizeof *r + strlen (curve)); + r->key = pSUBKEYCURVE; + strcpy (r->u.value, curve); + r->next = para; + para = r; + } } - else + else /* Create only a single key. */ { + /* For ECC we need to ask for the curve before storing the + algo becuase ask_curve may change the algo. */ + if (algo == PUBKEY_ALGO_ECDSA + || algo == PUBKEY_ALGO_EDDSA + || algo == PUBKEY_ALGO_ECDH) + { + curve = ask_curve (&algo); + nbits = 0; + r = xmalloc_clear (sizeof *r + strlen (curve)); + r->key = pKEYCURVE; + strcpy (r->u.value, curve); + r->next = para; + para = r; + } + r = xmalloc_clear( sizeof *r + 20 ); r->key = pKEYTYPE; sprintf( r->u.value, "%d", algo ); @@ -3528,13 +3588,7 @@ generate_keypair (ctrl_t ctrl, const char *fname, const char *card_serialno, || algo == PUBKEY_ALGO_EDDSA || algo == PUBKEY_ALGO_ECDH) { - if (!both) - curve = ask_curve (); - r = xmalloc_clear (sizeof *r + strlen (curve)); - r->key = both? pSUBKEYCURVE : pKEYCURVE; - strcpy (r->u.value, curve); - r->next = para; - para = r; + /* The curve has already been set. */ } else { @@ -4031,11 +4085,7 @@ generate_subkeypair (ctrl_t ctrl, kbnode_t keyblock) else if (algo == PUBKEY_ALGO_ECDSA || algo == PUBKEY_ALGO_EDDSA || algo == PUBKEY_ALGO_ECDH) - { - curve = ask_curve (); - if (curve && !strcmp (curve, "Ed25519")) - algo = PUBKEY_ALGO_EDDSA; - } + curve = ask_curve (&algo); else nbits = ask_keysize (algo, 0); diff --git a/g10/parse-packet.c b/g10/parse-packet.c index f708788..424b052 100644 --- a/g10/parse-packet.c +++ b/g10/parse-packet.c @@ -2240,6 +2240,11 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, pk->pkey[npkey] = gcry_mpi_set_opaque (NULL, read_rest (inp, pktlen), pktlen * 8); + /* Mark that MPI as protected - we need this information for + importing a key. The OPAQUE flag can't be used because + we also store public EdDSA values in opaque MPIs. */ + if (pk->pkey[npkey]) + gcry_mpi_set_flag (pk->pkey[npkey], GCRYMPI_FLAG_USER1); pktlen = 0; if (list_mode) es_fprintf (listfp, "\tskey[%d]: [v4 protected]\n", npkey); @@ -2252,6 +2257,8 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen, if (ski->is_protected) { pk->pkey[i] = read_protected_v3_mpi (inp, &pktlen); + if (pk->pkey[i]) + gcry_mpi_set_flag (pk->pkey[i], GCRYMPI_FLAG_USER1); if (list_mode) es_fprintf (listfp, "\tskey[%d]: [v3 protected]\n", i); } diff --git a/tests/openpgp/ecc.test b/tests/openpgp/ecc.test index 062a1ae..cb04467 100755 --- a/tests/openpgp/ecc.test +++ b/tests/openpgp/ecc.test @@ -188,7 +188,7 @@ echo 'This is one line' >z for msg in $tests; do info "checking: $msg" eval "(IFS=; echo \"\$$msg\")" >x - $GPG -o y --yes x || error "decryption of $msg failed" + PINENTRY_USER_DATA=ecc $GPG -o y --yes x || error "decryption of $msg failed" cmp y z || error "$msg: mismatch" done @@ -204,7 +204,7 @@ for i in $plain_files $data_files ; do for k in $mainkeyids ; do info "file: $i key: $k" $GPG ${opt_always} -e -o x --yes -r $k $i - $GPG -o y --yes x + PINENTRY_USER_DATA=ecc $GPG -o y --yes x cmp $i y || error "$i,$k: mismatch" done done @@ -217,7 +217,7 @@ info "Checking ECC signing and verifiction." for i in $plain_files $data_files ; do for k in $mainkeyids ; do info "file: $i key: $k" - $GPG -s -o x --yes -u $k $i + PINENTRY_USER_DATA=ecc $GPG -s -o x --yes -u $k $i $GPG -o y --yes x || error "verify of $i,$k failed" cmp $i y || error "$i,$k: mismatch" done commit bdb9c2b314400da9155b8a924e22e486793dda89 Author: Werner Koch Date: Wed May 7 12:39:43 2014 +0200 kbx: Add experimental support for EDDSA. * kbx/keybox-openpgp.c (parse_key): Use algo constants and add experimental support for EdDSA. diff --git a/kbx/keybox-openpgp.c b/kbx/keybox-openpgp.c index 82bc934..6ae6c44 100644 --- a/kbx/keybox-openpgp.c +++ b/kbx/keybox-openpgp.c @@ -199,23 +199,24 @@ parse_key (const unsigned char *data, size_t datalen, switch (algorithm) { - case 1: - case 2: - case 3: /* RSA */ + case PUBKEY_ALGO_RSA: + case PUBKEY_ALGO_RSA_E: + case PUBKEY_ALGO_RSA_S: npkey = 2; break; - case 16: - case 20: /* Elgamal */ + case PUBKEY_ALGO_ELGAMAL_E: + case PUBKEY_ALGO_ELGAMAL: npkey = 3; break; - case 17: /* DSA */ + case PUBKEY_ALGO_DSA: npkey = 4; break; - case 18: /* ECDH */ + case PUBKEY_ALGO_ECDH: npkey = 3; is_ecc = 1; break; - case 19: /* ECDSA */ + case PUBKEY_ALGO_ECDSA: + case PUBKEY_ALGO_EDDSA: npkey = 2; is_ecc = 1; break; commit a63ed9875830e5b3b4d48b7d97d24c18de36b326 Author: Werner Koch Date: Wed May 7 08:51:11 2014 +0200 agent: Remove greeting message. * agent/gpg-agent.c (main): Remove greeting. Make --no-greeting a dummy. diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 5319e49..9ec13ee 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -612,8 +612,6 @@ main (int argc, char **argv ) unsigned configlineno; int parse_debug = 0; int default_config =1; - int greeting = 0; - int nogreeting = 0; int pipe_server = 0; int is_daemon = 0; int nodetach = 0; @@ -811,7 +809,7 @@ main (int argc, char **argv ) goto next_pass; } break; - case oNoGreeting: nogreeting = 1; break; + case oNoGreeting: /* Dummy option. */ break; case oNoVerbose: opt.verbose = 0; break; case oNoOptions: break; /* no-options */ case oHomedir: opt.homedir = pargs.r.ret_str; break; @@ -882,25 +880,10 @@ main (int argc, char **argv ) configname = NULL; if (log_get_errorcount(0)) exit(2); - if (nogreeting ) - greeting = 0; /* Turn the homedir into an absolute one. */ opt.homedir = make_absfilename (opt.homedir, NULL); - - if (greeting) - { - es_fprintf (es_stderr, "%s %s; %s\n", - strusage(11), strusage(13), strusage(14) ); - es_fprintf (es_stderr, "%s\n", strusage(15) ); - } -#ifdef IS_DEVELOPMENT_VERSION - /* We don't want to print it here because gpg-agent is useful of its - own and quite matured. */ - /*log_info ("NOTE: this is a development version!\n");*/ -#endif - /* Print a warning if an argument looks like an option. */ if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN)) { commit 6477e51919ef97f0f9cc05d10cdc7aa2b89faafe Author: Werner Koch Date: Tue May 6 09:49:26 2014 +0200 Use "samethread" mode keyword for some es_fopenmem. * dirmngr/ks-engine-hkp.c (armor_data): Add mode keyword. * g10/call-dirmngr.c (ks_put_inq_cb): Ditto. * scd/atr.c (atr_dump): Ditto. diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c index c115cf5..8c3384d 100644 --- a/dirmngr/ks-engine-hkp.c +++ b/dirmngr/ks-engine-hkp.c @@ -925,7 +925,7 @@ armor_data (char **r_string, const void *data, size_t datalen) *r_string = NULL; - fp = es_fopenmem (0, "rw"); + fp = es_fopenmem (0, "rw,samethread"); if (!fp) return gpg_error_from_syserror (); diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c index 73f829e..5bddbbe 100644 --- a/g10/call-dirmngr.c +++ b/g10/call-dirmngr.c @@ -593,7 +593,7 @@ ks_put_inq_cb (void *opaque, const char *line) estream_t fp; /* Parse the keyblock and send info lines back to the server. */ - fp = es_fopenmem (0, "rw"); + fp = es_fopenmem (0, "rw,samethread"); if (!fp) err = gpg_error_from_syserror (); diff --git a/scd/atr.c b/scd/atr.c index b8668a4..c3fa49f 100644 --- a/scd/atr.c +++ b/scd/atr.c @@ -50,7 +50,7 @@ atr_dump (const void *buffer, size_t buflen) unsigned char chksum; char *result; - fp = es_fopenmem (0, "rwb"); + fp = es_fopenmem (0, "rwb,samethread"); if (!fp) return NULL; ----------------------------------------------------------------------- Summary of changes: agent/cvt-openpgp.c | 184 +++++++------ agent/gpg-agent.c | 19 +- agent/keyformat.txt | 2 + common/openpgp-oid.c | 9 +- dirmngr/ks-engine-hkp.c | 2 +- g10/call-dirmngr.c | 2 +- g10/import.c | 140 +++------- g10/keygen.c | 116 +++++--- g10/keylist.c | 16 +- g10/mainproc.c | 686 ++++++++++++++++++++++++----------------------- g10/misc.c | 4 +- g10/parse-packet.c | 7 + kbx/keybox-openpgp.c | 17 +- scd/atr.c | 2 +- tests/openpgp/ecc.test | 6 +- 15 files changed, 605 insertions(+), 607 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Wed May 7 16:36:09 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 07 May 2014 16:36:09 +0200 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-414-g57011da 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 57011da53e43f9c8a6c7e7314166c3e17ff8627a (commit) from 359c643d747c890f73f68b42e0aeb896016f05fd (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 57011da53e43f9c8a6c7e7314166c3e17ff8627a Author: Werner Koch Date: Wed May 7 16:37:15 2014 +0200 Make -jN work again. * common/Makefile.am ($(PROGRAMS)): New rule (t_http_LDADD): Use libcommontls.a without directory prefix. * dirmngr/Makefile.am ($(PROGRAMS)): New rule. diff --git a/common/Makefile.am b/common/Makefile.am index 439c29b..b955539 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -220,4 +220,7 @@ t_zb32_LDADD = $(t_common_ldadd) # http tests t_http_SOURCES = t-http.c t_http_CFLAGS = $(t_common_cflags) $(LIBGNUTLS_CFLAGS) -t_http_LDADD = $(libcommontls) $(t_common_ldadd) $(LIBGNUTLS_LIBS) $(DNSLIBS) +t_http_LDADD = libcommontls.a $(t_common_ldadd) $(LIBGNUTLS_LIBS) $(DNSLIBS) + +# All programs should depend on the created libs. +$(PROGRAMS) : libcommon.a libcommonpth.a libcommontls.a libcommontlsnpth.a diff --git a/dirmngr/Makefile.am b/dirmngr/Makefile.am index b5bef45..7e2449f 100644 --- a/dirmngr/Makefile.am +++ b/dirmngr/Makefile.am @@ -87,3 +87,6 @@ dirmngr_client_LDFLAGS = $(extra_bin_ldflags) no-libgcrypt.c : $(top_srcdir)/tools/no-libgcrypt.c cat $(top_srcdir)/tools/no-libgcrypt.c > no-libgcrypt.c + + +$(PROGRAMS) : $(libcommon) $(libcommonpth) $(libcommontls) $(libcommontlsnpth) ----------------------------------------------------------------------- Summary of changes: common/Makefile.am | 5 ++++- dirmngr/Makefile.am | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Thu May 8 04:45:27 2014 From: cvs at cvs.gnupg.org (by NIIBE Yutaka) Date: Thu, 08 May 2014 04:45:27 +0200 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-415-gfb24808 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 fb24808db9af9dfe36f9f6d7fc24e0b903ecc12c (commit) from 57011da53e43f9c8a6c7e7314166c3e17ff8627a (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 fb24808db9af9dfe36f9f6d7fc24e0b903ecc12c Author: NIIBE Yutaka Date: Thu May 8 11:46:38 2014 +0900 agent: Fix auth key comment handling. * agent/command-ssh.c (ssh_send_key_public): Handle the case with no comment. diff --git a/agent/command-ssh.c b/agent/command-ssh.c index a814681..d619324 100644 --- a/agent/command-ssh.c +++ b/agent/command-ssh.c @@ -2331,7 +2331,9 @@ ssh_send_key_public (estream_t stream, gcry_sexp_t key, else { err = ssh_key_extract_comment (key, &comment); - if (!err) + if (err) + err = stream_write_cstring (stream, "(none)"); + else err = stream_write_cstring (stream, comment); } if (err) ----------------------------------------------------------------------- Summary of changes: agent/command-ssh.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Thu May 8 10:30:27 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Thu, 08 May 2014 10:30:27 +0200 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-417-g4aeb025 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 4aeb02562c9db4b96366220b781e2b4fa2d6fd3b (commit) via cb2aeb4e1157fc0d7dc25d94115973422dc1a800 (commit) from fb24808db9af9dfe36f9f6d7fc24e0b903ecc12c (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 4aeb02562c9db4b96366220b781e2b4fa2d6fd3b Author: Werner Koch Date: Thu May 8 10:24:36 2014 +0200 agent: Fix import of non-protected gpg keys. * agent/cvt-openpgp.c (do_unprotect): Return an s-exp also for non-protected keys. (convert_from_openpgp_main): Do not call agent_askpin for a non-protected key. diff --git a/agent/cvt-openpgp.c b/agent/cvt-openpgp.c index 28f0380..7f4afd4 100644 --- a/agent/cvt-openpgp.c +++ b/agent/cvt-openpgp.c @@ -397,7 +397,8 @@ do_unprotect (const char *passphrase, if (actual_csum != desired_csum) return gpg_error (GPG_ERR_CHECKSUM); - return 0; + + goto do_convert; } @@ -595,6 +596,7 @@ do_unprotect (const char *passphrase, if (actual_csum != desired_csum) return gpg_error (GPG_ERR_BAD_PASSPHRASE); + do_convert: if (nskey != skeylen) err = gpg_error (GPG_ERR_BAD_SECKEY); else @@ -905,7 +907,11 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp, pi_arg.r_key = &s_skey; err = gpg_error (GPG_ERR_BAD_PASSPHRASE); - if (cache_nonce) + if (!is_protected) + { + err = try_do_unprotect_cb (pi); + } + else if (cache_nonce) { char *cache_value; @@ -928,7 +934,7 @@ convert_from_openpgp_main (ctrl_t ctrl, gcry_sexp_t s_pgp, if (gpg_err_code (err) == GPG_ERR_BAD_PASSPHRASE && !from_native) err = agent_askpin (ctrl, prompt, NULL, NULL, pi); skeyidx = pi_arg.skeyidx; - if (!err && r_passphrase) + if (!err && r_passphrase && is_protected) { *r_passphrase = xtrystrdup (pi->pin); if (!*r_passphrase) commit cb2aeb4e1157fc0d7dc25d94115973422dc1a800 Author: Werner Koch Date: Wed May 7 18:18:27 2014 +0200 Make more use of *_NAME macros. * configure.ac (GPG_DISP_NAME, GPGSM_DISP_NAME): New. (GPG_AGENT_DISP_NAME, SCDAEMON_DISP_NAME): New. (DIRMNGR_DISP_NAME, G13_DISP_NAME): New. (GPGCONF_DISP_NAME): New. (SCDAEMON_SOCK_NAME): New. * common/argparse.c (show_help): Map description string. diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c index 9ec13ee..096d057 100644 --- a/agent/gpg-agent.c +++ b/agent/gpg-agent.c @@ -747,7 +747,8 @@ main (int argc, char **argv ) */ if (default_config) - configname = make_filename (opt.homedir, "gpg-agent.conf", NULL ); + configname = make_filename (opt.homedir, GPG_AGENT_NAME EXTSEP_S "conf", + NULL ); argc = orig_argc; argv = orig_argv; @@ -956,11 +957,13 @@ main (int argc, char **argv ) char *filename_esc; /* List options and default values in the GPG Conf format. */ - filename = make_filename (opt.homedir, "gpg-agent.conf", NULL ); + filename = make_filename (opt.homedir, GPG_AGENT_NAME EXTSEP_S "conf", + NULL ); filename_esc = percent_escape (filename, NULL); - es_printf ("gpgconf-gpg-agent.conf:%lu:\"%s\n", - GC_OPT_FLAG_DEFAULT, filename_esc); + es_printf ("%s-%s.conf:%lu:\"%s\n", + GPGCONF_NAME, GPG_AGENT_NAME, + GC_OPT_FLAG_DEFAULT, filename_esc); xfree (filename); xfree (filename_esc); diff --git a/common/argparse.c b/common/argparse.c index 6d18bd4..f4180cf 100644 --- a/common/argparse.c +++ b/common/argparse.c @@ -1126,7 +1126,7 @@ show_help (ARGPARSE_OPTS *opts, unsigned int flags) writestrings (0, "Options:", "\n", NULL); for (i=0; opts[i].short_opt; i++ ) { - s = _( opts[i].description ); + s = map_static_macro_string (_( opts[i].description )); if ( s && *s== '@' && !s[1] ) /* Hide this line. */ continue; if ( s && *s == '@' ) /* Unindented comment only line. */ diff --git a/configure.ac b/configure.ac index 21f5fb6..ae42f7e 100644 --- a/configure.ac +++ b/configure.ac @@ -1689,13 +1689,32 @@ fi # Define Name strings # AC_DEFINE_UNQUOTED(GNUPG_NAME, "GnuPG", [The name of the project]) + AC_DEFINE_UNQUOTED(GPG_NAME, "gpg", [The name of the OpenPGP tool]) +AC_DEFINE_UNQUOTED(GPG_DISP_NAME, "GnuPG", [The displayed name of gpg]) + AC_DEFINE_UNQUOTED(GPGSM_NAME, "gpgsm", [The name of the S/MIME tool]) +AC_DEFINE_UNQUOTED(GPGSM_DISP_NAME, "GPGSM", [The displayed name of gpgsm]) + AC_DEFINE_UNQUOTED(GPG_AGENT_NAME, "gpg-agent", [The name of the agent]) +AC_DEFINE_UNQUOTED(GPG_AGENT_DISP_NAME, "GPG Agent", + [The displayed name of gpg-agent]) + AC_DEFINE_UNQUOTED(SCDAEMON_NAME, "scdaemon", [The name of the scdaemon]) +AC_DEFINE_UNQUOTED(SCDAEMON_DISP_NAME, "SCDaemon", + [The displayed name of scdaemon]) + AC_DEFINE_UNQUOTED(DIRMNGR_NAME, "dirmngr", [The name of the dirmngr]) +AC_DEFINE_UNQUOTED(DIRMNGR_DISP_NAME, "DirMngr", + [The displayed name of dirmngr]) + AC_DEFINE_UNQUOTED(G13_NAME, "g13", [The name of the g13 tool]) +AC_DEFINE_UNQUOTED(G13_DISP_NAME, "G13", [The displayed name of g13]) + AC_DEFINE_UNQUOTED(GPGCONF_NAME, "gpgconf", [The name of the gpgconf tool]) +AC_DEFINE_UNQUOTED(GPGCONF_DISP_NAME, "GPGConf", + [The displayed name of gpgconf]) + AC_DEFINE_UNQUOTED(GPGTAR_NAME, "gpgtar", [The name of the gpgtar tool]) AC_DEFINE_UNQUOTED(GPG_AGENT_INFO_NAME, "GPG_AGENT_INFO", @@ -1706,6 +1725,8 @@ AC_DEFINE_UNQUOTED(GPG_AGENT_SSH_SOCK_NAME, "S.gpg-agent.ssh", [The name of the agent socket for ssh]) AC_DEFINE_UNQUOTED(DIRMNGR_INFO_NAME, "DIRMNGR_INFO", [The name of the dirmngr info envvar]) +AC_DEFINE_UNQUOTED(SCDAEMON_SOCK_NAME, "S.scdaemon", + [The name of the SCdaemon socket]) AC_DEFINE_UNQUOTED(DIRMNGR_SOCK_NAME, "S.dirmngr", [The name of the dirmngr socket]) diff --git a/g10/gpg.c b/g10/gpg.c index daae3d3..fa3e8c2 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -1697,7 +1697,8 @@ gpgconf_list (const char *configfile) { char *configfile_esc = percent_escape (configfile, NULL); - es_printf ("gpgconf-gpg.conf:%lu:\"%s\n", + es_printf ("%s-%s.conf:%lu:\"%s\n", + GPGCONF_NAME, GPG_NAME, GC_OPT_FLAG_DEFAULT, configfile_esc ? configfile_esc : "/dev/null"); es_printf ("verbose:%lu:\n", GC_OPT_FLAG_NONE); diff --git a/g10/keyedit.c b/g10/keyedit.c index 9e5fb8f..a91beaf 100644 --- a/g10/keyedit.c +++ b/g10/keyedit.c @@ -1590,7 +1590,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr, #ifdef HAVE_LIBREADLINE tty_enable_completion (keyedit_completion); #endif - answer = cpr_get_no_help ("keyedit.prompt", "gpg> "); + answer = cpr_get_no_help ("keyedit.prompt", GPG_NAME "> "); cpr_kill_prompt (); tty_disable_completion (); } diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 6fe11f8..aa15883 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -489,7 +489,8 @@ main (int argc, char **argv ) if (default_config) - configname = make_filename (opt.homedir, "scdaemon.conf", NULL ); + configname = make_filename (opt.homedir, SCDAEMON_NAME EXTSEP_S "conf", + NULL ); argc = orig_argc; @@ -659,10 +660,12 @@ main (int argc, char **argv ) if (config_filename) filename = xstrdup (config_filename); else - filename = make_filename (opt.homedir, "scdaemon.conf", NULL); + filename = make_filename (opt.homedir, SCDAEMON_NAME EXTSEP_S "conf", + NULL); filename_esc = percent_escape (filename, NULL); - es_printf ("gpgconf-scdaemon.conf:%lu:\"%s\n", + es_printf ("%s-%s.conf:%lu:\"%s\n", + GPGCONF_NAME, SCDAEMON_NAME, GC_OPT_FLAG_DEFAULT, filename_esc); xfree (filename_esc); xfree (filename); @@ -742,8 +745,8 @@ main (int argc, char **argv ) if (multi_server) { socket_name = create_socket_name (standard_socket, - "S.scdaemon", - "gpg-XXXXXX/S.scdaemon"); + SCDAEMON_SOCK_NAME, + "gpg-XXXXXX/" SCDAEMON_SOCK_NAME); fd = FD2INT(create_server_socket (standard_socket, socket_name, &socket_nonce)); @@ -798,8 +801,8 @@ main (int argc, char **argv ) /* Create the socket. */ socket_name = create_socket_name (standard_socket, - "S.scdaemon", - "gpg-XXXXXX/S.scdaemon"); + SCDAEMON_SOCK_NAME, + "gpg-XXXXXX/" SCDAEMON_SOCK_NAME); fd = FD2INT (create_server_socket (standard_socket, socket_name, &socket_nonce)); diff --git a/sm/gpgsm.c b/sm/gpgsm.c index 9199a3f..3822717 100644 --- a/sm/gpgsm.c +++ b/sm/gpgsm.c @@ -899,7 +899,7 @@ main ( int argc, char **argv) /*mtrace();*/ - gnupg_reopen_std ("gpgsm"); + gnupg_reopen_std (GPGSM_NAME); /* trap_unaligned ();*/ gnupg_rl_initialize (); set_strusage (my_strusage); @@ -908,7 +908,7 @@ main ( int argc, char **argv) /* Please note that we may running SUID(ROOT), so be very CAREFUL when adding any stuff between here and the call to secmem_init() somewhere after the option parsing */ - log_set_prefix ("gpgsm", 1); + log_set_prefix (GPGSM_NAME, 1); /* Make sure that our subsystems are ready. */ i18n_init (); @@ -998,7 +998,7 @@ main ( int argc, char **argv) /* Set the default option file */ if (default_config ) - configname = make_filename (opt.homedir, "gpgsm.conf", NULL); + configname = make_filename (opt.homedir, GPGSM_NAME EXTSEP_S "conf", NULL); /* Set the default policy file */ opt.policy_file = make_filename (opt.homedir, "policies.txt", NULL); @@ -1422,7 +1422,8 @@ main ( int argc, char **argv) configname = NULL; if (!opt.config_filename) - opt.config_filename = make_filename (opt.homedir, "gpgsm.conf", NULL); + opt.config_filename = make_filename (opt.homedir, GPG_NAME EXTSEP_S "conf", + NULL); if (log_get_errorcount(0)) gpgsm_exit(2); @@ -1653,7 +1654,8 @@ main ( int argc, char **argv) { /* List options and default values in the GPG Conf format. */ char *config_filename_esc = percent_escape (opt.config_filename, NULL); - es_printf ("gpgconf-gpgsm.conf:%lu:\"%s\n", + es_printf ("%s-%s.conf:%lu:\"%s\n", + GPGCONF_NAME, GPGSM_NAME, GC_OPT_FLAG_DEFAULT, config_filename_esc); xfree (config_filename_esc); diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c index 65c116b..f9999ba 100644 --- a/tools/gpgconf-comp.c +++ b/tools/gpgconf-comp.c @@ -180,20 +180,20 @@ static struct } gc_backend[GC_BACKEND_NR] = { { NULL }, /* GC_BACKEND_ANY dummy entry. */ - { GNUPG_NAME, GPGNAME, GNUPG_MODULE_NAME_GPG, - NULL, "gpgconf-gpg.conf" }, - { "GPGSM", GPGSM_NAME, GNUPG_MODULE_NAME_GPGSM, - NULL, "gpgconf-gpgsm.conf" }, - { "GPG Agent", GPG_AGENT_NAME, GNUPG_MODULE_NAME_AGENT, - gpg_agent_runtime_change, "gpgconf-gpg-agent.conf" }, - { "SCDaemon", SCDAEMON_NAME, GNUPG_MODULE_NAME_SCDAEMON, - scdaemon_runtime_change, "gpgconf-scdaemon.conf" }, - { "DirMngr", DIRMNGR_NAME, GNUPG_MODULE_NAME_DIRMNGR, - NULL, "gpgconf-dirmngr.conf" }, - { "DirMngr LDAP Server List", NULL, 0, + { GPG_DISP_NAME, GPGNAME, GNUPG_MODULE_NAME_GPG, + NULL, GPGCONF_NAME "-" GPG_NAME ".conf" }, + { GPGSM_DISP_NAME, GPGSM_NAME, GNUPG_MODULE_NAME_GPGSM, + NULL, GPGCONF_NAME "-" GPGSM_NAME ".conf" }, + { GPG_AGENT_DISP_NAME, GPG_AGENT_NAME, GNUPG_MODULE_NAME_AGENT, + gpg_agent_runtime_change, GPGCONF_NAME"-" GPG_AGENT_NAME ".conf" }, + { SCDAEMON_DISP_NAME, SCDAEMON_NAME, GNUPG_MODULE_NAME_SCDAEMON, + scdaemon_runtime_change, GPGCONF_NAME"-" SCDAEMON_NAME ".conf" }, + { DIRMNGR_DISP_NAME, DIRMNGR_NAME, GNUPG_MODULE_NAME_DIRMNGR, + NULL, GPGCONF_NAME "-" DIRMNGR_NAME ".conf" }, + { DIRMNGR_DISP_NAME " LDAP Server List", NULL, 0, NULL, "ldapserverlist-file", "LDAP Server" }, { "Pinentry", "pinentry", GNUPG_MODULE_NAME_PINENTRY, - NULL, "gpgconf-pinentry.conf" }, + NULL, GPGCONF_NAME "-pinentry.conf" }, }; @@ -470,7 +470,8 @@ typedef struct gc_option gc_option_t; static gc_option_t gc_options_gpg_agent[] = { /* The configuration file to which we write the changes. */ - { "gpgconf-gpg-agent.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, + { GPGCONF_NAME"-" GPG_AGENT_NAME ".conf", + GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG_AGENT }, { "Monitor", @@ -584,7 +585,8 @@ static gc_option_t gc_options_gpg_agent[] = static gc_option_t gc_options_scdaemon[] = { /* The configuration file to which we write the changes. */ - { "gpgconf-scdaemon.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, + { GPGCONF_NAME"-"SCDAEMON_NAME".conf", + GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_SCDAEMON }, { "Monitor", @@ -658,7 +660,8 @@ static gc_option_t gc_options_scdaemon[] = static gc_option_t gc_options_gpg[] = { /* The configuration file to which we write the changes. */ - { "gpgconf-gpg.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, + { GPGCONF_NAME"-"GPG_NAME".conf", + GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPG }, { "Monitor", @@ -736,7 +739,8 @@ static gc_option_t gc_options_gpg[] = static gc_option_t gc_options_gpgsm[] = { /* The configuration file to which we write the changes. */ - { "gpgconf-gpgsm.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, + { GPGCONF_NAME"-"GPGSM_NAME".conf", + GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_GPGSM }, { "Monitor", @@ -831,7 +835,8 @@ static gc_option_t gc_options_gpgsm[] = static gc_option_t gc_options_dirmngr[] = { /* The configuration file to which we write the changes. */ - { "gpgconf-dirmngr.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, + { GPGCONF_NAME"-"DIRMNGR_NAME".conf", + GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_DIRMNGR }, { "Monitor", @@ -973,7 +978,8 @@ static gc_option_t gc_options_pinentry[] = { /* A dummy option to allow gc_component_list_components to find the pinentry backend. Needs to be a conf file. */ - { "gpgconf-pinentry.conf", GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, + { GPGCONF_NAME"-pinentry.conf", + GC_OPT_FLAG_NONE, GC_LEVEL_INTERNAL, NULL, NULL, GC_ARG_TYPE_FILENAME, GC_BACKEND_PINENTRY }, GC_OPTION_NULL @@ -2414,7 +2420,7 @@ change_options_file (gc_component_t component, gc_backend_t backend, char **src_filenamep, char **dest_filenamep, char **orig_filenamep) { - static const char marker[] = "###+++--- GPGConf ---+++###"; + static const char marker[] = "###+++--- " GPGCONF_DISP_NAME " ---+++###"; /* True if we are within the marker in the config file. */ int in_marker = 0; gc_option_t *option; @@ -2441,8 +2447,10 @@ change_options_file (gc_component_t component, gc_backend_t backend, /* Note that get_config_filename() calls percent_deescape(), so we call this before processing the arguments. */ dest_filename = xstrdup (get_config_filename (component, backend)); - src_filename = xasprintf ("%s.gpgconf.%i.new", dest_filename, (int)getpid ()); - orig_filename = xasprintf ("%s.gpgconf.%i.bak", dest_filename,(int)getpid ()); + src_filename = xasprintf ("%s.%s.%i.new", + dest_filename, GPGCONF_NAME, (int)getpid ()); + orig_filename = xasprintf ("%s.%s.%i.bak", + dest_filename, GPGCONF_NAME, (int)getpid ()); arg = option->new_value; if (arg && arg[0] == '\0') @@ -2579,8 +2587,8 @@ change_options_file (gc_component_t component, gc_backend_t backend, if (!in_marker) { fprintf (src_file, - "# GPGConf disabled this option here at %s\n", - asctimestamp (gnupg_get_time ())); + "# %s disabled this option here at %s\n", + GPGCONF_DISP_NAME, asctimestamp (gnupg_get_time ())); if (ferror (src_file)) goto change_file_one_err; fprintf (src_file, "# %s", line); @@ -2648,7 +2656,8 @@ change_options_file (gc_component_t component, gc_backend_t backend, if (!in_marker) { - fprintf (src_file, "# GPGConf edited this configuration file.\n"); + fprintf (src_file, "# %s edited this configuration file.\n", + GPGCONF_DISP_NAME); if (ferror (src_file)) goto change_file_one_err; fprintf (src_file, "# It will disable options before this marked " @@ -2714,7 +2723,7 @@ change_options_program (gc_component_t component, gc_backend_t backend, char **src_filenamep, char **dest_filenamep, char **orig_filenamep) { - static const char marker[] = "###+++--- GPGConf ---+++###"; + static const char marker[] = "###+++--- " GPGCONF_DISP_NAME " ---+++###"; /* True if we are within the marker in the config file. */ int in_marker = 0; gc_option_t *option; @@ -2733,8 +2742,10 @@ change_options_program (gc_component_t component, gc_backend_t backend, /* FIXME. Throughout the function, do better error reporting. */ dest_filename = xstrdup (get_config_filename (component, backend)); - src_filename = xasprintf ("%s.gpgconf.%i.new", dest_filename, (int)getpid ()); - orig_filename = xasprintf ("%s.gpgconf.%i.bak", dest_filename,(int)getpid ()); + src_filename = xasprintf ("%s.%s.%i.new", + dest_filename, GPGCONF_NAME, (int)getpid ()); + orig_filename = xasprintf ("%s.%s.%i.bak", + dest_filename, GPGCONF_NAME, (int)getpid ()); #ifdef HAVE_W32_SYSTEM res = copy_file (dest_filename, orig_filename); @@ -2825,8 +2836,8 @@ change_options_program (gc_component_t component, gc_backend_t backend, if (!in_marker) { fprintf (src_file, - "# GPGConf disabled this option here at %s\n", - asctimestamp (gnupg_get_time ())); + "# %s disabled this option here at %s\n", + GPGCONF_DISP_NAME, asctimestamp (gnupg_get_time ())); if (ferror (src_file)) goto change_one_err; fprintf (src_file, "# %s", line); @@ -2946,7 +2957,8 @@ change_options_program (gc_component_t component, gc_backend_t backend, if (!in_marker) { - fprintf (src_file, "# GPGConf edited this configuration file.\n"); + fprintf (src_file, "# %s edited this configuration file.\n", + GPGCONF_DISP_NAME); if (ferror (src_file)) goto change_one_err; fprintf (src_file, "# It will disable options before this marked " @@ -3287,7 +3299,8 @@ gc_component_change_options (int component, estream_t in, estream_t out) assert (dest_filename[backend]); - backup_filename = xasprintf ("%s.gpgconf.bak", dest_filename[backend]); + backup_filename = xasprintf ("%s.%s.bak", + dest_filename[backend], GPGCONF_NAME); #ifdef HAVE_W32_SYSTEM /* There is no atomic update on W32. */ @@ -3436,7 +3449,8 @@ gc_process_gpgconf_conf (const char *fname_arg, int update, int defaults, if (fname_arg) fname = xstrdup (fname_arg); else - fname = make_filename (gnupg_sysconfdir (), "gpgconf.conf", NULL); + fname = make_filename (gnupg_sysconfdir (), GPGCONF_NAME EXTSEP_S "conf", + NULL); for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++) runtime[backend_id] = 0; diff --git a/tools/gpgconf.c b/tools/gpgconf.c index 96313f6..cb37a25 100644 --- a/tools/gpgconf.c +++ b/tools/gpgconf.c @@ -70,7 +70,7 @@ static ARGPARSE_OPTS opts[] = { aApplyDefaults, "apply-defaults", 256, N_("apply global default values") }, { aListDirs, "list-dirs", 256, - N_("get the configuration directories for gpgconf") }, + N_("get the configuration directories for @GPGCONF@") }, { aListConfig, "list-config", 256, N_("list global configuration file") }, { aCheckConfig, "check-config", 256, @@ -151,9 +151,9 @@ main (int argc, char **argv) enum cmd_and_opt_values cmd = 0; estream_t outfp = NULL; - gnupg_reopen_std ("gpgconf"); + gnupg_reopen_std (GPGCONF_NAME); set_strusage (my_strusage); - log_set_prefix ("gpgconf", 1); + log_set_prefix (GPGCONF_NAME, 1); /* Make sure that our subsystems are ready. */ i18n_init(); @@ -228,7 +228,7 @@ main (int argc, char **argv) case aCheckOptions: if (!fname) { - es_fputs (_("usage: gpgconf [options] "), es_stderr); + es_fprintf (es_stderr, _("usage: %s [options] "), GPGCONF_NAME); es_putc ('\n', es_stderr); es_fputs (_("Need one component argument"), es_stderr); es_putc ('\n', es_stderr); @@ -262,7 +262,7 @@ main (int argc, char **argv) case aKill: if (!fname) { - es_fputs (_("usage: gpgconf [options] "), es_stderr); + es_fprintf (es_stderr, _("usage: %s [options] "), GPGCONF_NAME); es_putc ('\n', es_stderr); es_fputs (_("Need one component argument"), es_stderr); es_putc ('\n', es_stderr); @@ -325,7 +325,7 @@ main (int argc, char **argv) case aApplyDefaults: if (fname) { - es_fputs (_("usage: gpgconf [options] "), es_stderr); + es_fprintf (es_stderr, _("usage: %s [options] "), GPGCONF_NAME); es_putc ('\n', es_stderr); es_fputs (_("No argument allowed"), es_stderr); es_putc ('\n', es_stderr); diff --git a/tools/gpgtar.c b/tools/gpgtar.c index e484986..e9a25fb 100644 --- a/tools/gpgtar.c +++ b/tools/gpgtar.c @@ -172,9 +172,9 @@ main (int argc, char **argv) assert (sizeof (struct ustar_raw_header) == 512); - gnupg_reopen_std ("gpgtar"); + gnupg_reopen_std (GPGTAR_NAME); set_strusage (my_strusage); - log_set_prefix ("gpgtar", 1); + log_set_prefix (GPGTAR_NAME, 1); /* Make sure that our subsystems are ready. */ i18n_init(); ----------------------------------------------------------------------- Summary of changes: agent/cvt-openpgp.c | 12 ++++++-- agent/gpg-agent.c | 11 ++++--- common/argparse.c | 2 +- configure.ac | 21 ++++++++++++++ g10/gpg.c | 3 +- g10/keyedit.c | 2 +- scd/scdaemon.c | 17 ++++++----- sm/gpgsm.c | 12 ++++---- tools/gpgconf-comp.c | 78 +++++++++++++++++++++++++++++--------------------- tools/gpgconf.c | 12 ++++---- tools/gpgtar.c | 4 +-- 11 files changed, 112 insertions(+), 62 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Thu May 8 11:30:29 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Thu, 08 May 2014 11:30:29 +0200 Subject: [git] GPGME - branch, master, updated. gpgme-1.4.3-26-g991cde9 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 991cde9e79fec70aad093ded383c5574d30f9388 (commit) from 62711e5614e44e65a7c7bb7d21493d09d3081271 (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 991cde9e79fec70aad093ded383c5574d30f9388 Author: Werner Koch Date: Thu May 8 11:31:30 2014 +0200 Add GPGME_ENCRYPT_NO_COMPRESS flag. * src/gpgme.h.in (GPGME_ENCRYPT_NO_COMPRESS): New. * src/engine-gpg.c (gpg_encrypt, gpg_encrypt_sign): Implement it. * src/gpgme-tool.c (_cmd_sign_encrypt): Add option --no-compress. diff --git a/NEWS b/NEWS index acba24d..5fb4808 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,8 @@ Noteworthy changes in version 1.5.0 (unreleased) * Add feature to use the gpgme I/O subsystem to run arbitrary commands. + * Add flag to force encryption without the default comprtession step. + * Interface changes relative to the 1.4.3 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gpgme_get_dirinfo NEW. @@ -20,6 +22,7 @@ Noteworthy changes in version 1.5.0 (unreleased) GPGME_PROTOCOL_SPAWN NEW. GPGME_SPAWN_DETACHED NEW. GPGME_SPAWN_ALLOW_SET_FG NEW. + GPGME_ENCRYPT_NO_COMPRESS NEW. Noteworthy changes in version 1.4.3 (2013-08-12) diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 7697ff1..eaf1fcb 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -5141,6 +5141,21 @@ The @code{GPGME_ENCRYPT_NO_ENCRYPT_TO} symbol specifies that no default or hidden default recipients as configured in the crypto backend should be included. This can be useful for managing different user profiles. + + at item GPGME_ENCRYPT_NO_COMPRESS +The @code{GPGME_ENCRYPT_NO_COMPRESS} symbol specifies that the +plaintext shall not be compressed before it is encrypted. This is +in some cases useful if the length of the encrypted message +may reveal information about the plaintext. + + at item GPGME_ENCRYPT_PREPARE + at itemx GPGME_ENCRYPT_EXPECT_SIGN +The @code{GPGME_ENCRYPT_PREPARE} symbol is used with the UI Server +protocol to prepare an encryption (i.e. sending the + at code{PREP_ENCRYPT} command). With the + at code{GPGME_ENCRYPT_EXPECT_SIGN} symbol the UI Server is advised to +also expect a sign command. + @end table If @code{GPG_ERR_UNUSABLE_PUBKEY} is returned, some recipients in diff --git a/src/engine-gpg.c b/src/engine-gpg.c index ce9e349..ede098e 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -1662,6 +1662,9 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags, if (!err && use_armor) err = add_arg (gpg, "--armor"); + if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS)) + err = add_arg (gpg, "--compress-algo=none"); + if (!symmetric) { /* If we know that all recipients are valid (full or ultimate trust) @@ -1719,6 +1722,9 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[], if (!err && use_armor) err = add_arg (gpg, "--armor"); + if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS)) + err = add_arg (gpg, "--compress-algo=none"); + if (!symmetric) { /* If we know that all recipients are valid (full or ultimate trust) diff --git a/src/gpgme-tool.c b/src/gpgme-tool.c index a980347..be8ed07 100644 --- a/src/gpgme-tool.c +++ b/src/gpgme-tool.c @@ -2806,6 +2806,8 @@ _cmd_sign_encrypt (assuan_context_t ctx, char *line, int sign) flags |= GPGME_ENCRYPT_PREPARE; if (strstr (line, "--expect-sign")) flags |= GPGME_ENCRYPT_EXPECT_SIGN; + if (strstr (line, "--no-compress")) + flags |= GPGME_ENCRYPT_NO_COMPRESS; inp_fd = server->input_fd; inp_fn = server->input_filename; @@ -2842,7 +2844,7 @@ _cmd_sign_encrypt (assuan_context_t ctx, char *line, int sign) static const char hlp_encrypt[] = "ENCRYPT [--always-trust] [--no-encrypt-to]\n" - " [--prepare] [--expect-sign]\n" + " [--no-compress] [--prepare] [--expect-sign]\n" "\n" "Encrypt the object set by the last INPUT command to\n" "the keys specified by previous RECIPIENT commands. \n" @@ -2857,7 +2859,7 @@ cmd_encrypt (assuan_context_t ctx, char *line) static const char hlp_sign_encrypt[] = "SIGN_ENCRYPT [--always-trust] [--no-encrypt-to]\n" - " [--prepare] [--expect-sign]\n" + " [--no-compress] [--prepare] [--expect-sign]\n" "\n" "Sign the object set by the last INPUT command with the\n" "keys specified by previous SIGNER commands and encrypt\n" diff --git a/src/gpgme.h.in b/src/gpgme.h.in index 655602d..efc58ea 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -1283,7 +1283,8 @@ typedef enum GPGME_ENCRYPT_ALWAYS_TRUST = 1, GPGME_ENCRYPT_NO_ENCRYPT_TO = 2, GPGME_ENCRYPT_PREPARE = 4, - GPGME_ENCRYPT_EXPECT_SIGN = 8 + GPGME_ENCRYPT_EXPECT_SIGN = 8, + GPGME_ENCRYPT_NO_COMPRESS = 16 } gpgme_encrypt_flags_t; ----------------------------------------------------------------------- Summary of changes: NEWS | 3 +++ doc/gpgme.texi | 15 +++++++++++++++ src/engine-gpg.c | 6 ++++++ src/gpgme-tool.c | 6 ++++-- src/gpgme.h.in | 3 ++- 5 files changed, 30 insertions(+), 3 deletions(-) hooks/post-receive -- GnuPG Made Easy http://git.gnupg.org From cvs at cvs.gnupg.org Thu May 8 14:12:04 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Thu, 08 May 2014 14:12:04 +0200 Subject: [git] GPGME - branch, master, updated. gpgme-1.4.3-27-gd5fb92c 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 d5fb92cdaed21eea2f1a921e4f11df72635a8462 (commit) from 991cde9e79fec70aad093ded383c5574d30f9388 (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 d5fb92cdaed21eea2f1a921e4f11df72635a8462 Author: Werner Koch Date: Thu May 8 14:03:14 2014 +0200 Map public key algos returned by gpg to gpgme values. * src/conversion.c (_gpgme_map_pk_algo): New. * src/decrypt.c (parse_enc_to): Add arg PROTOCOL and map pubkey algo. (_gpgme_decrypt_status_handler): Map pubkey algo. * src/keylist.c (keylist_colon_handler): Map pubkey algo. * src/sign.c (parse_sig_created): Add arg PROTOCOL and map pubkey algo. * src/verify.c (parse_new_sig): Ditto. (parse_valid_sig): Ditto. * src/gpgme.h.in (GPGME_PK_ECC): New. (GPGME_MD_SHA224): New. * src/gpgme.c (gpgme_pubkey_algo_name): Add GPGME_PK_ECC case. (gpgme_hash_algo_name): Add GPGME_MD_SHA224. -- This affects only the not yet released ECC code of GnuPG 2.1. diff --git a/NEWS b/NEWS index 5fb4808..b9d2f35 100644 --- a/NEWS +++ b/NEWS @@ -12,7 +12,7 @@ Noteworthy changes in version 1.5.0 (unreleased) * Add feature to use the gpgme I/O subsystem to run arbitrary commands. - * Add flag to force encryption without the default comprtession step. + * Add flag to force encryption without the default compression step. * Interface changes relative to the 1.4.3 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -23,6 +23,8 @@ Noteworthy changes in version 1.5.0 (unreleased) GPGME_SPAWN_DETACHED NEW. GPGME_SPAWN_ALLOW_SET_FG NEW. GPGME_ENCRYPT_NO_COMPRESS NEW. + GPGME_PK_ECC NEW. + GPGME_MD_SHA224 NEW. Noteworthy changes in version 1.4.3 (2013-08-12) diff --git a/doc/gpgme.texi b/doc/gpgme.texi index eaf1fcb..9a67c3b 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -1135,16 +1135,16 @@ This value indicates ElGamal. @item GPGME_PK_ELG_E This value also indicates ElGamal and is used specifically in GnuPG. - at item GPGME_PK_ELG_E -This value also indicates ElGamal and is used specifically in GnuPG. + at item GPGME_PK_ECC +This value is a generic indicator for ellipic curve algorithms. @item GPGME_PK_ECDSA This value indicates ECDSA, the Elliptic Curve Digital Signature -Algorithm as defined by FIPS 186-2. +Algorithm as defined by FIPS 186-2 and RFC-6637. @item GPGME_PK_ECDH -This value indicates ECDH, the Eliptic Curve Diffie-Hellmann encryption -algorithm as defined by the ECC in OpenPGP draft. +This value indicates ECDH, the Eliptic Curve Diffie-Hellmann +encryption algorithm as defined by RFC-6637. @end table @end deftp @@ -1185,6 +1185,7 @@ that are supported by @acronym{GPGME}. Possible values are: @item GPGME_MD_SHA256 @item GPGME_MD_SHA384 @item GPGME_MD_SHA512 + at item GPGME_MD_SHA224 @item GPGME_MD_MD4 @item GPGME_MD_CRC32 @item GPGME_MD_CRC32_RFC1510 diff --git a/src/conversion.c b/src/conversion.c index b47d6de..d04a6be 100644 --- a/src/conversion.c +++ b/src/conversion.c @@ -412,3 +412,24 @@ _gpgme_parse_timestamp (const char *timestamp, char **endp) else return (time_t)strtoul (timestamp, endp, 10); } + + +/* The GPG backend uses OpenPGP algorithm numbers which we need to map + to our algorithm numbers. This function MUST not change ERRNO. */ +int +_gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol) +{ + if (protocol == GPGME_PROTOCOL_OPENPGP) + { + switch (algo) + { + case 1: case 2: case 3: case 16: case 17: break; + case 18: algo = GPGME_PK_ECDH; break; + case 19: algo = GPGME_PK_ECDSA; break; + case 20: break; + default: algo = 0; break; /* Unknown. */ + } + } + + return algo; +} diff --git a/src/decrypt.c b/src/decrypt.c index 63787c7..4742060 100644 --- a/src/decrypt.c +++ b/src/decrypt.c @@ -119,7 +119,7 @@ gpgme_op_decrypt_result (gpgme_ctx_t ctx) static gpgme_error_t -parse_enc_to (char *args, gpgme_recipient_t *recp) +parse_enc_to (char *args, gpgme_recipient_t *recp, gpgme_protocol_t protocol) { gpgme_recipient_t rec; char *tail; @@ -155,7 +155,7 @@ parse_enc_to (char *args, gpgme_recipient_t *recp) if (*args) { gpg_err_set_errno (0); - rec->pubkey_algo = strtol (args, &tail, 0); + rec->pubkey_algo = _gpgme_map_pk_algo (strtol (args, &tail, 0), protocol); if (errno || args == tail || *tail != ' ') { /* The crypto backend does not behave. */ @@ -261,7 +261,7 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code, break; case GPGME_STATUS_ENC_TO: - err = parse_enc_to (args, opd->last_recipient_p); + err = parse_enc_to (args, opd->last_recipient_p, ctx->protocol); if (err) return err; diff --git a/src/gpgme.c b/src/gpgme.c index 24b04fc..a3768ef 100644 --- a/src/gpgme.c +++ b/src/gpgme.c @@ -948,6 +948,9 @@ gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo) case GPGME_PK_DSA: return "DSA"; + case GPGME_PK_ECC: + return "ECC"; + case GPGME_PK_ELG: return "ELG"; @@ -995,6 +998,9 @@ gpgme_hash_algo_name (gpgme_hash_algo_t algo) case GPGME_MD_SHA512: return "SHA512"; + case GPGME_MD_SHA224: + return "SHA224"; + case GPGME_MD_MD4: return "MD4"; diff --git a/src/gpgme.h.in b/src/gpgme.h.in index efc58ea..d58c114 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -227,7 +227,7 @@ typedef enum gpgme_data_type_t; -/* Public key algorithms from libgcrypt. */ +/* Public key algorithms. */ typedef enum { GPGME_PK_RSA = 1, @@ -235,6 +235,7 @@ typedef enum GPGME_PK_RSA_S = 3, GPGME_PK_ELG_E = 16, GPGME_PK_DSA = 17, + GPGME_PK_ECC = 18, GPGME_PK_ELG = 20, GPGME_PK_ECDSA = 301, GPGME_PK_ECDH = 302 @@ -242,7 +243,7 @@ typedef enum gpgme_pubkey_algo_t; -/* Hash algorithms from libgcrypt. */ +/* Hash algorithms (the values match those from libgcrypt). */ typedef enum { GPGME_MD_NONE = 0, @@ -255,6 +256,7 @@ typedef enum GPGME_MD_SHA256 = 8, GPGME_MD_SHA384 = 9, GPGME_MD_SHA512 = 10, + GPGME_MD_SHA224 = 11, GPGME_MD_MD4 = 301, GPGME_MD_CRC32 = 302, GPGME_MD_CRC32_RFC1510 = 303, diff --git a/src/keylist.c b/src/keylist.c index 465b472..a361333 100644 --- a/src/keylist.c +++ b/src/keylist.c @@ -537,7 +537,7 @@ keylist_colon_handler (void *priv, char *line) { int i = atoi (field[3]); if (i >= 1 && i < 128) - subkey->pubkey_algo = i; + subkey->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol); } /* Field 5 has the long keyid. Allow short key IDs for the @@ -614,7 +614,7 @@ keylist_colon_handler (void *priv, char *line) { int i = atoi (field[3]); if (i >= 1 && i < 128) - subkey->pubkey_algo = i; + subkey->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol); } /* Field 5 has the long keyid. */ @@ -728,7 +728,7 @@ keylist_colon_handler (void *priv, char *line) { int i = atoi (field[3]); if (i >= 1 && i < 128) - keysig->pubkey_algo = i; + keysig->pubkey_algo = _gpgme_map_pk_algo (i, ctx->protocol); } /* Field 5 has the long keyid. */ diff --git a/src/sign.c b/src/sign.c index e910799..c55441d 100644 --- a/src/sign.c +++ b/src/sign.c @@ -142,7 +142,8 @@ gpgme_op_sign_result (gpgme_ctx_t ctx) static gpgme_error_t -parse_sig_created (char *args, gpgme_new_signature_t *sigp) +parse_sig_created (char *args, gpgme_new_signature_t *sigp, + gpgme_protocol_t protocol) { gpgme_new_signature_t sig; char *tail; @@ -180,7 +181,7 @@ parse_sig_created (char *args, gpgme_new_signature_t *sigp) } gpg_err_set_errno (0); - sig->pubkey_algo = strtol (args, &tail, 0); + sig->pubkey_algo = _gpgme_map_pk_algo (strtol (args, &tail, 0), protocol); if (errno || args == tail || *tail != ' ') { /* The crypto backend does not behave. */ @@ -263,7 +264,7 @@ _gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args) { case GPGME_STATUS_SIG_CREATED: opd->sig_created_seen = 1; - err = parse_sig_created (args, opd->last_sig_p); + err = parse_sig_created (args, opd->last_sig_p, ctx->protocol); if (err) return err; diff --git a/src/util.h b/src/util.h index 4b46ea0..365f1d8 100644 --- a/src/util.h +++ b/src/util.h @@ -135,6 +135,8 @@ time_t _gpgme_parse_timestamp (const char *timestamp, char **endp); gpgme_error_t _gpgme_map_gnupg_error (char *err); +int _gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol); + /* Retrieve the environment variable NAME and return a copy of it in a malloc()'ed buffer in *VALUE. If the environment variable is not diff --git a/src/verify.c b/src/verify.c index c32241a..37b2bd4 100644 --- a/src/verify.c +++ b/src/verify.c @@ -264,7 +264,8 @@ prepare_new_sig (op_data_t opd) } static gpgme_error_t -parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args) +parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args, + gpgme_protocol_t protocol) { gpgme_signature_t sig; char *end = strchr (args, ' '); @@ -318,7 +319,7 @@ parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args) if (!end) goto parse_err_sig_fail; gpg_err_set_errno (0); - sig->pubkey_algo = strtol (end, &tail, 0); + sig->pubkey_algo = _gpgme_map_pk_algo (strtol (end, &tail, 0), protocol); if (errno || end == tail || *tail != ' ') goto parse_err_sig_fail; end = tail; @@ -393,7 +394,7 @@ parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args) static gpgme_error_t -parse_valid_sig (gpgme_signature_t sig, char *args) +parse_valid_sig (gpgme_signature_t sig, char *args, gpgme_protocol_t protocol) { char *end = strchr (args, ' '); if (end) @@ -443,7 +444,8 @@ parse_valid_sig (gpgme_signature_t sig, char *args) { /* Parse the pubkey algo. */ gpg_err_set_errno (0); - sig->pubkey_algo = strtol (end, &tail, 0); + sig->pubkey_algo = _gpgme_map_pk_algo (strtol (end, &tail, 0), + protocol); if (errno || end == tail || *tail != ' ') return trace_gpg_error (GPG_ERR_INV_ENGINE); end = tail; @@ -703,11 +705,11 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args) if (sig && !opd->did_prepare_new_sig) calc_sig_summary (sig); opd->only_newsig_seen = 0; - return parse_new_sig (opd, code, args); + return parse_new_sig (opd, code, args, ctx->protocol); case GPGME_STATUS_VALIDSIG: opd->only_newsig_seen = 0; - return sig ? parse_valid_sig (sig, args) + return sig ? parse_valid_sig (sig, args, ctx->protocol) : trace_gpg_error (GPG_ERR_INV_ENGINE); case GPGME_STATUS_NODATA: ----------------------------------------------------------------------- Summary of changes: NEWS | 4 +++- doc/gpgme.texi | 11 ++++++----- src/conversion.c | 21 +++++++++++++++++++++ src/decrypt.c | 6 +++--- src/gpgme.c | 6 ++++++ src/gpgme.h.in | 6 ++++-- src/keylist.c | 6 +++--- src/sign.c | 7 ++++--- src/util.h | 2 ++ src/verify.c | 14 ++++++++------ 10 files changed, 60 insertions(+), 23 deletions(-) hooks/post-receive -- GnuPG Made Easy http://git.gnupg.org From cvs at cvs.gnupg.org Thu May 8 20:38:07 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Thu, 08 May 2014 20:38:07 +0200 Subject: [git] GPGME - branch, master, updated. gpgme-1.4.3-29-g88f1533 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 88f15336ec0eadde68ff2618349efb9006b8e801 (commit) via de4a1ea684e1591975feb801e7651309e1ee2c49 (commit) from d5fb92cdaed21eea2f1a921e4f11df72635a8462 (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 88f15336ec0eadde68ff2618349efb9006b8e801 Author: Werner Koch Date: Thu May 8 20:39:15 2014 +0200 Add field CURVE to the key info. * src/gpgme.h.in (struct _gpgme_subkey): Add field CURVE. * src/key.c (gpgme_key_unref): Free CURVE. * src/keylist.c (keylist_colon_handler): Set CURVE. * src/gpgme.c (gpgme_release): For failsafe reasons reset engine and engine info after freeing. -- The engine hack is useful in case the other release functions accidently call engine release. diff --git a/NEWS b/NEWS index b9d2f35..9433356 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,7 @@ Noteworthy changes in version 1.5.0 (unreleased) GPGME_ENCRYPT_NO_COMPRESS NEW. GPGME_PK_ECC NEW. GPGME_MD_SHA224 NEW. + gpgme_subkey_t EXTENDED: New field curve. Noteworthy changes in version 1.4.3 (2013-08-12) diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 9a67c3b..e326574 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -2742,6 +2742,10 @@ True if the secret key is stored on a smart card. @item char *card_number The serial number of a smart card holding this key or @code{NULL}. + + at item char *curve +For ECC algoritms the name of the curve. + @end table @end deftp diff --git a/src/gpgme.c b/src/gpgme.c index a3768ef..628cdae 100644 --- a/src/gpgme.c +++ b/src/gpgme.c @@ -233,6 +233,7 @@ gpgme_release (gpgme_ctx_t ctx) return; _gpgme_engine_release (ctx->engine); + ctx->engine = NULL; _gpgme_fd_table_deinit (&ctx->fdt); _gpgme_release_result (ctx); _gpgme_signers_clear (ctx); @@ -244,6 +245,7 @@ gpgme_release (gpgme_ctx_t ctx) if (ctx->lc_messages) free (ctx->lc_messages); _gpgme_engine_info_release (ctx->engine_info); + ctx->engine_info = NULL; DESTROY_LOCK (ctx->lock); free (ctx); } diff --git a/src/gpgme.h.in b/src/gpgme.h.in index d58c114..170d7dd 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -629,6 +629,9 @@ struct _gpgme_subkey /* The serial number of a smart card holding this key or NULL. */ char *card_number; + + /* The name of the curve for ECC algorithms or NULL. */ + char *curve; }; typedef struct _gpgme_subkey *gpgme_subkey_t; diff --git a/src/key.c b/src/key.c index 59d4908..1a68966 100644 --- a/src/key.c +++ b/src/key.c @@ -331,6 +331,8 @@ gpgme_key_unref (gpgme_key_t key) gpgme_subkey_t next = subkey->next; if (subkey->fpr) free (subkey->fpr); + if (subkey->curve) + free (subkey->curve); if (subkey->card_number) free (subkey->card_number); free (subkey); diff --git a/src/keylist.c b/src/keylist.c index a361333..582b241 100644 --- a/src/keylist.c +++ b/src/keylist.c @@ -422,7 +422,7 @@ keylist_colon_handler (void *priv, char *line) RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK } rectype = RT_NONE; -#define NR_FIELDS 16 +#define NR_FIELDS 17 char *field[NR_FIELDS]; int fields = 0; void *hook; @@ -584,6 +584,15 @@ keylist_colon_handler (void *priv, char *line) if (err) return err; } + + /* Field 17 has the curve name for ECC. */ + if (fields >= 17 && *field[16]) + { + subkey->curve = strdup (field[16]); + if (!subkey->curve) + return gpg_error_from_syserror (); + } + break; case RT_SUB: @@ -646,6 +655,15 @@ keylist_colon_handler (void *priv, char *line) if (err) return err; } + + /* Field 17 has the curve name for ECC. */ + if (fields >= 17 && *field[16]) + { + subkey->curve = strdup (field[16]); + if (!subkey->curve) + return gpg_error_from_syserror (); + } + break; case RT_UID: commit de4a1ea684e1591975feb801e7651309e1ee2c49 Author: Werner Koch Date: Thu May 8 20:35:57 2014 +0200 Fix a memory access and a double slash bug. * src/engine-spawn.c (engspawn_start): Allocate space for list terminator. * src/posix-util.c (walk_path): Fix trailing slash detection. -- Kudos to Valgrind for pointing out these two problems. The first is a plain allocation bug in a code pattern I have written thousands of times - this time it went wrong. The allocation is not user controlled thus not directly exploitable. The second is missed to do what it intended to do. Found due to the access of malloced but not initialized memory. Not using calloc again proved to be helpful to detect logical error. diff --git a/src/engine-spawn.c b/src/engine-spawn.c index bfcad3d..8ffc628 100644 --- a/src/engine-spawn.c +++ b/src/engine-spawn.c @@ -250,7 +250,7 @@ engspawn_start (engine_spawn_t esp, const char *file, const char *argv[], n = 0; for (i = 0; esp->fd_data_map[i].data; i++) n++; - fd_list = calloc (n, sizeof *fd_list); + fd_list = calloc (n+1, sizeof *fd_list); if (!fd_list) return gpg_error_from_syserror (); diff --git a/src/posix-util.c b/src/posix-util.c index e78cd77..f7e0a17 100644 --- a/src/posix-util.c +++ b/src/posix-util.c @@ -95,7 +95,7 @@ walk_path (const char *pgm) { for (s=path, p=fname; *s && *s != ':'; s++, p++) *p = *s; - if (*p != '/') + if (p != fname && p[-1] != '/') *p++ = '/'; strcpy (p, pgm); if (!access (fname, X_OK)) ----------------------------------------------------------------------- Summary of changes: NEWS | 1 + doc/gpgme.texi | 4 ++++ src/engine-spawn.c | 2 +- src/gpgme.c | 2 ++ src/gpgme.h.in | 3 +++ src/key.c | 2 ++ src/keylist.c | 20 +++++++++++++++++++- src/posix-util.c | 2 +- 8 files changed, 33 insertions(+), 3 deletions(-) hooks/post-receive -- GnuPG Made Easy http://git.gnupg.org From cvs at cvs.gnupg.org Fri May 9 13:22:36 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Fri, 09 May 2014 13:22:36 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-67-g246b7aa 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 246b7aaae1ee459f440260bbc4ec2c01c5dc3362 (commit) via 42f097486eb1ab92f30fdab56865eec4af685def (commit) from fc6ff6f73a51bcbbbb3757dc1386da40aa3ae75d (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 246b7aaae1ee459f440260bbc4ec2c01c5dc3362 Author: Werner Koch Date: Fri May 9 12:35:15 2014 +0200 mpi: Fix a subtle bug setting spurious bits with in mpi_set_bit. * mpi/mpi-bit.c (_gcry_mpi_set_bit, _gcry_mpi_set_highbit): Clear allocated but not used bits before resizing. * tests/t-mpi-bits.c (set_bit_with_resize): New. -- Reported-by: Martin Sewelies. This bug is probably with us for many years. Probably due to different memory allocation patterns, it did first revealed itself with 1.6. It could be the reason for other heisenbugs. Signed-off-by: Werner Koch diff --git a/mpi/mpi-bit.c b/mpi/mpi-bit.c index fcafda0..e217040 100644 --- a/mpi/mpi-bit.c +++ b/mpi/mpi-bit.c @@ -116,7 +116,7 @@ _gcry_mpi_test_bit( gcry_mpi_t a, unsigned int n ) void _gcry_mpi_set_bit( gcry_mpi_t a, unsigned int n ) { - unsigned int limbno, bitno; + unsigned int i, limbno, bitno; if (mpi_is_immutable (a)) { @@ -129,6 +129,8 @@ _gcry_mpi_set_bit( gcry_mpi_t a, unsigned int n ) if ( limbno >= a->nlimbs ) { + for (i=a->nlimbs; i < a->alloced; i++) + a->d[i] = 0; mpi_resize (a, limbno+1 ); a->nlimbs = limbno+1; } @@ -141,7 +143,7 @@ _gcry_mpi_set_bit( gcry_mpi_t a, unsigned int n ) void _gcry_mpi_set_highbit( gcry_mpi_t a, unsigned int n ) { - unsigned int limbno, bitno; + unsigned int i, limbno, bitno; if (mpi_is_immutable (a)) { @@ -154,6 +156,8 @@ _gcry_mpi_set_highbit( gcry_mpi_t a, unsigned int n ) if ( limbno >= a->nlimbs ) { + for (i=a->nlimbs; i < a->alloced; i++) + a->d[i] = 0; mpi_resize (a, limbno+1 ); a->nlimbs = limbno+1; } diff --git a/tests/t-mpi-bit.c b/tests/t-mpi-bit.c index b1c999e..3d7b793 100644 --- a/tests/t-mpi-bit.c +++ b/tests/t-mpi-bit.c @@ -327,6 +327,58 @@ test_lshift (int pass) } +/* Bug fixed on 2014-05-09: + a = gcry_mpi_new (1523); + gcry_mpi_set_bit (a, 1536); + didn't initialized all limbs in A. */ +static void +set_bit_with_resize (void) +{ + gcry_mpi_t a; + int i; + + wherestr = "set_bit_with_resize"; + show ("checking that set_bit initializes all limbs\n"); + + a = gcry_mpi_new (1536); + gcry_mpi_set_bit (a, 1536); + + if (!gcry_mpi_test_bit (a, 1536)) + fail ("failed to set a bit\n"); + for (i=0; i < 1536; i++) + { + if (gcry_mpi_test_bit (a, i)) + { + fail ("spurious bit detected\n"); + break; + } + } + if (gcry_mpi_test_bit (a, 1537)) + fail ("more bits set than expected\n"); + gcry_mpi_release (a); + + wherestr = "set_highbit_with_resize"; + show ("checking that set_highbit initializes all limbs\n"); + + a = gcry_mpi_new (1536); + gcry_mpi_set_highbit (a, 1536); + + if (!gcry_mpi_test_bit (a, 1536)) + fail ("failed to set a bit\n"); + for (i=0; i < 1536; i++) + { + if (gcry_mpi_test_bit (a, i)) + { + fail ("spurious bit detected\n"); + break; + } + } + if (gcry_mpi_test_bit (a, 1537)) + fail ("more bits set than expected\n"); + gcry_mpi_release (a); +} + + int main (int argc, char **argv) { @@ -356,6 +408,8 @@ main (int argc, char **argv) for (i=0; i < 5; i++) test_lshift (i); /* Run several times due to random initializations. */ + set_bit_with_resize (); + show ("All tests completed. Errors: %d\n", error_count); return error_count ? 1 : 0; } commit 42f097486eb1ab92f30fdab56865eec4af685def Author: Werner Koch Date: Fri May 9 12:11:30 2014 +0200 Comment typo fix -- diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c index 1f1754a..fdce578 100644 --- a/mpi/mpiutil.c +++ b/mpi/mpiutil.c @@ -28,7 +28,7 @@ #include "mpi-internal.h" #include "mod-source-info.h" -/* Constatns allocated right away at strtartup. */ +/* Constants allocated right away at startup. */ static gcry_mpi_t constants[MPI_NUMBER_OF_CONSTANTS]; ----------------------------------------------------------------------- Summary of changes: mpi/mpi-bit.c | 8 ++++++-- mpi/mpiutil.c | 2 +- tests/t-mpi-bit.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Fri May 9 13:28:19 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Fri, 09 May 2014 13:28:19 +0200 Subject: [git] GCRYPT - branch, LIBGCRYPT-1-6-BRANCH, updated. libgcrypt-1.6.1-11-gaf75f62 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, LIBGCRYPT-1-6-BRANCH has been updated via af75f6294f5aad8228241cdc32a883352f2150ea (commit) via 534b04eb1077f53d13b6e5f80ba7d07db1eae4b1 (commit) from e438beb82565dc777406ef4b847dcca33e0ad2d8 (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 af75f6294f5aad8228241cdc32a883352f2150ea Author: Werner Koch Date: Fri May 9 12:35:15 2014 +0200 mpi: Fix a subtle bug setting spurious bits with in mpi_set_bit. * mpi/mpi-bit.c (_gcry_mpi_set_bit, _gcry_mpi_set_highbit): Clear allocated but not used bits before resizing. * tests/t-mpi-bits.c (set_bit_with_resize): New. -- Reported-by: Martin Sewelies. This bug is probably with us for many years. Probably due to different memory allocation patterns, it did first revealed itself with 1.6. It could be the reason for other heisenbugs. Signed-off-by: Werner Koch diff --git a/mpi/mpi-bit.c b/mpi/mpi-bit.c index fcafda0..e217040 100644 --- a/mpi/mpi-bit.c +++ b/mpi/mpi-bit.c @@ -116,7 +116,7 @@ _gcry_mpi_test_bit( gcry_mpi_t a, unsigned int n ) void _gcry_mpi_set_bit( gcry_mpi_t a, unsigned int n ) { - unsigned int limbno, bitno; + unsigned int i, limbno, bitno; if (mpi_is_immutable (a)) { @@ -129,6 +129,8 @@ _gcry_mpi_set_bit( gcry_mpi_t a, unsigned int n ) if ( limbno >= a->nlimbs ) { + for (i=a->nlimbs; i < a->alloced; i++) + a->d[i] = 0; mpi_resize (a, limbno+1 ); a->nlimbs = limbno+1; } @@ -141,7 +143,7 @@ _gcry_mpi_set_bit( gcry_mpi_t a, unsigned int n ) void _gcry_mpi_set_highbit( gcry_mpi_t a, unsigned int n ) { - unsigned int limbno, bitno; + unsigned int i, limbno, bitno; if (mpi_is_immutable (a)) { @@ -154,6 +156,8 @@ _gcry_mpi_set_highbit( gcry_mpi_t a, unsigned int n ) if ( limbno >= a->nlimbs ) { + for (i=a->nlimbs; i < a->alloced; i++) + a->d[i] = 0; mpi_resize (a, limbno+1 ); a->nlimbs = limbno+1; } diff --git a/tests/t-mpi-bit.c b/tests/t-mpi-bit.c index b1c999e..3d7b793 100644 --- a/tests/t-mpi-bit.c +++ b/tests/t-mpi-bit.c @@ -327,6 +327,58 @@ test_lshift (int pass) } +/* Bug fixed on 2014-05-09: + a = gcry_mpi_new (1523); + gcry_mpi_set_bit (a, 1536); + didn't initialized all limbs in A. */ +static void +set_bit_with_resize (void) +{ + gcry_mpi_t a; + int i; + + wherestr = "set_bit_with_resize"; + show ("checking that set_bit initializes all limbs\n"); + + a = gcry_mpi_new (1536); + gcry_mpi_set_bit (a, 1536); + + if (!gcry_mpi_test_bit (a, 1536)) + fail ("failed to set a bit\n"); + for (i=0; i < 1536; i++) + { + if (gcry_mpi_test_bit (a, i)) + { + fail ("spurious bit detected\n"); + break; + } + } + if (gcry_mpi_test_bit (a, 1537)) + fail ("more bits set than expected\n"); + gcry_mpi_release (a); + + wherestr = "set_highbit_with_resize"; + show ("checking that set_highbit initializes all limbs\n"); + + a = gcry_mpi_new (1536); + gcry_mpi_set_highbit (a, 1536); + + if (!gcry_mpi_test_bit (a, 1536)) + fail ("failed to set a bit\n"); + for (i=0; i < 1536; i++) + { + if (gcry_mpi_test_bit (a, i)) + { + fail ("spurious bit detected\n"); + break; + } + } + if (gcry_mpi_test_bit (a, 1537)) + fail ("more bits set than expected\n"); + gcry_mpi_release (a); +} + + int main (int argc, char **argv) { @@ -356,6 +408,8 @@ main (int argc, char **argv) for (i=0; i < 5; i++) test_lshift (i); /* Run several times due to random initializations. */ + set_bit_with_resize (); + show ("All tests completed. Errors: %d\n", error_count); return error_count ? 1 : 0; } commit 534b04eb1077f53d13b6e5f80ba7d07db1eae4b1 Author: Werner Koch Date: Fri May 9 12:11:30 2014 +0200 Comment typo fix -- diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c index 1f1754a..fdce578 100644 --- a/mpi/mpiutil.c +++ b/mpi/mpiutil.c @@ -28,7 +28,7 @@ #include "mpi-internal.h" #include "mod-source-info.h" -/* Constatns allocated right away at strtartup. */ +/* Constants allocated right away at startup. */ static gcry_mpi_t constants[MPI_NUMBER_OF_CONSTANTS]; ----------------------------------------------------------------------- Summary of changes: mpi/mpi-bit.c | 8 ++++++-- mpi/mpiutil.c | 2 +- tests/t-mpi-bit.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Sun May 11 11:06:09 2014 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sun, 11 May 2014 11:06:09 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-70-ga39ee75 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 a39ee7555691d18cae97560f130aaf952bfbd278 (commit) via def7d4cad386271c6d4e2f10aabe0cb4abd871e4 (commit) via 23f33d57c9b6f2295a8ddfc9a8eee5a2c30cf406 (commit) from 246b7aaae1ee459f440260bbc4ec2c01c5dc3362 (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 a39ee7555691d18cae97560f130aaf952bfbd278 Author: Jussi Kivilinna Date: Sun May 11 12:00:19 2014 +0300 chacha20: add AVX2/AMD64 assembly implementation * cipher/Makefile.am: Add 'chacha20-avx2-amd64.S'. * cipher/chacha20-avx2-amd64.S: New. * cipher/chacha20.c (USE_AVX2): New macro. [USE_AVX2] (_gcry_chacha20_amd64_avx2_blocks): New. (chacha20_do_setkey): Select AVX2 implementation if there is HW support. (selftest): Increase size of buf by 256. * configure.ac [host=x86-64]: Add 'chacha20-avx2-amd64.lo'. -- Add AVX2 optimized implementation for ChaCha20. Based on implementation by Andrew Moon. SSSE3 (Intel Haswell): CHACHA20 | nanosecs/byte mebibytes/sec cycles/byte STREAM enc | 0.742 ns/B 1284.8 MiB/s 2.38 c/B STREAM dec | 0.741 ns/B 1286.5 MiB/s 2.37 c/B AVX2: CHACHA20 | nanosecs/byte mebibytes/sec cycles/byte STREAM enc | 0.393 ns/B 2428.0 MiB/s 1.26 c/B STREAM dec | 0.392 ns/B 2433.6 MiB/s 1.25 c/B Signed-off-by: Jussi Kivilinna diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 27ca7ac..26d13d2 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -59,7 +59,7 @@ EXTRA_libcipher_la_SOURCES = \ arcfour.c arcfour-amd64.S \ blowfish.c blowfish-amd64.S blowfish-arm.S \ cast5.c cast5-amd64.S cast5-arm.S \ -chacha20.c chacha20-ssse3-amd64.S \ +chacha20.c chacha20-ssse3-amd64.S chacha20-avx2-amd64.S \ crc.c \ des.c des-amd64.S \ dsa.c \ diff --git a/cipher/chacha20-avx2-amd64.S b/cipher/chacha20-avx2-amd64.S new file mode 100644 index 0000000..c50a0c0 --- /dev/null +++ b/cipher/chacha20-avx2-amd64.S @@ -0,0 +1,949 @@ +/* chacha20-avx2-amd64.S - AMD64/AVX2 implementation of ChaCha20 + * + * Copyright (C) 2014 Jussi Kivilinna + * + * 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, see . + */ + +/* + * Based on public domain implementation by Andrew Moon at + * https://github.com/floodyberry/chacha-opt + */ + +#ifdef __x86_64__ +#include + +#if defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) && \ + defined(HAVE_GCC_INLINE_ASM_AVX2) && USE_CHACHA20 + +#ifdef __PIC__ +# define RIP (%rip) +#else +# define RIP +#endif + +.text + +.align 8 +.globl _gcry_chacha20_amd64_avx2_blocks +.type _gcry_chacha20_amd64_avx2_blocks, at function; +_gcry_chacha20_amd64_avx2_blocks: +.Lchacha_blocks_avx2_local: + pushq %rbx + pushq %rbp + pushq %r12 + pushq %r13 + pushq %r14 + movq %rsp, %rbp + andq $~63, %rsp + subq $512, %rsp + leaq .LC RIP, %rax + vmovdqu 0(%rax), %xmm6 + vmovdqu 16(%rax), %xmm7 + vmovdqu 0(%rdi), %xmm8 + vmovdqu 16(%rdi), %xmm9 + vmovdqu 32(%rdi), %xmm10 + vmovdqu 48(%rdi), %xmm11 + movl $20, %eax + movq $1, %r9 + vmovdqa %xmm8, 0(%rsp) + vmovdqa %xmm9, 16(%rsp) + vmovdqa %xmm10, 32(%rsp) + vmovdqa %xmm11, 48(%rsp) + movq %rax, 64(%rsp) + vmovdqa %xmm6, 448(%rsp) + vmovdqa %xmm6, 464(%rsp) + vmovdqa %xmm7, 480(%rsp) + vmovdqa %xmm7, 496(%rsp) + cmpq $512, %rcx + jae .Lchacha_blocks_avx2_atleast512 + cmp $256, %rcx + jae .Lchacha_blocks_avx2_atleast256 + jmp .Lchacha_blocks_avx2_below256 + .p2align 6,,63 +.Lchacha_blocks_avx2_atleast512: + movq 48(%rsp), %rax + leaq 1(%rax), %r8 + leaq 2(%rax), %r9 + leaq 3(%rax), %r10 + leaq 4(%rax), %rbx + leaq 5(%rax), %r11 + leaq 6(%rax), %r12 + leaq 7(%rax), %r13 + leaq 8(%rax), %r14 + movl %eax, 128(%rsp) + movl %r8d, 4+128(%rsp) + movl %r9d, 8+128(%rsp) + movl %r10d, 12+128(%rsp) + movl %ebx, 16+128(%rsp) + movl %r11d, 20+128(%rsp) + movl %r12d, 24+128(%rsp) + movl %r13d, 28+128(%rsp) + shrq $32, %rax + shrq $32, %r8 + shrq $32, %r9 + shrq $32, %r10 + shrq $32, %rbx + shrq $32, %r11 + shrq $32, %r12 + shrq $32, %r13 + movl %eax, 160(%rsp) + movl %r8d, 4+160(%rsp) + movl %r9d, 8+160(%rsp) + movl %r10d, 12+160(%rsp) + movl %ebx, 16+160(%rsp) + movl %r11d, 20+160(%rsp) + movl %r12d, 24+160(%rsp) + movl %r13d, 28+160(%rsp) + movq %r14, 48(%rsp) + movq 64(%rsp), %rax + vpbroadcastd 0(%rsp), %ymm0 + vpbroadcastd 4+0(%rsp), %ymm1 + vpbroadcastd 8+0(%rsp), %ymm2 + vpbroadcastd 12+0(%rsp), %ymm3 + vpbroadcastd 16(%rsp), %ymm4 + vpbroadcastd 4+16(%rsp), %ymm5 + vpbroadcastd 8+16(%rsp), %ymm6 + vpbroadcastd 12+16(%rsp), %ymm7 + vpbroadcastd 32(%rsp), %ymm8 + vpbroadcastd 4+32(%rsp), %ymm9 + vpbroadcastd 8+32(%rsp), %ymm10 + vpbroadcastd 12+32(%rsp), %ymm11 + vpbroadcastd 8+48(%rsp), %ymm14 + vpbroadcastd 12+48(%rsp), %ymm15 + vmovdqa 128(%rsp), %ymm12 + vmovdqa 160(%rsp), %ymm13 +.Lchacha_blocks_avx2_mainloop1: + vpaddd %ymm0, %ymm4, %ymm0 + vpaddd %ymm1, %ymm5, %ymm1 + vpxor %ymm12, %ymm0, %ymm12 + vpxor %ymm13, %ymm1, %ymm13 + vpaddd %ymm2, %ymm6, %ymm2 + vpaddd %ymm3, %ymm7, %ymm3 + vpxor %ymm14, %ymm2, %ymm14 + vpxor %ymm15, %ymm3, %ymm15 + vpshufb 448(%rsp), %ymm12, %ymm12 + vpshufb 448(%rsp), %ymm13, %ymm13 + vpaddd %ymm8, %ymm12, %ymm8 + vpaddd %ymm9, %ymm13, %ymm9 + vpshufb 448(%rsp), %ymm14, %ymm14 + vpshufb 448(%rsp), %ymm15, %ymm15 + vpaddd %ymm10, %ymm14, %ymm10 + vpaddd %ymm11, %ymm15, %ymm11 + vmovdqa %ymm12, 96(%rsp) + vpxor %ymm4, %ymm8, %ymm4 + vpxor %ymm5, %ymm9, %ymm5 + vpslld $ 12, %ymm4, %ymm12 + vpsrld $20, %ymm4, %ymm4 + vpxor %ymm4, %ymm12, %ymm4 + vpslld $ 12, %ymm5, %ymm12 + vpsrld $20, %ymm5, %ymm5 + vpxor %ymm5, %ymm12, %ymm5 + vpxor %ymm6, %ymm10, %ymm6 + vpxor %ymm7, %ymm11, %ymm7 + vpslld $ 12, %ymm6, %ymm12 + vpsrld $20, %ymm6, %ymm6 + vpxor %ymm6, %ymm12, %ymm6 + vpslld $ 12, %ymm7, %ymm12 + vpsrld $20, %ymm7, %ymm7 + vpxor %ymm7, %ymm12, %ymm7 + vpaddd %ymm0, %ymm4, %ymm0 + vpaddd %ymm1, %ymm5, %ymm1 + vpxor 96(%rsp), %ymm0, %ymm12 + vpxor %ymm13, %ymm1, %ymm13 + vpaddd %ymm2, %ymm6, %ymm2 + vpaddd %ymm3, %ymm7, %ymm3 + vpxor %ymm14, %ymm2, %ymm14 + vpxor %ymm15, %ymm3, %ymm15 + vpshufb 480(%rsp), %ymm12, %ymm12 + vpshufb 480(%rsp), %ymm13, %ymm13 + vpaddd %ymm8, %ymm12, %ymm8 + vpaddd %ymm9, %ymm13, %ymm9 + vpshufb 480(%rsp), %ymm14, %ymm14 + vpshufb 480(%rsp), %ymm15, %ymm15 + vpaddd %ymm10, %ymm14, %ymm10 + vpaddd %ymm11, %ymm15, %ymm11 + vmovdqa %ymm12, 96(%rsp) + vpxor %ymm4, %ymm8, %ymm4 + vpxor %ymm5, %ymm9, %ymm5 + vpslld $ 7, %ymm4, %ymm12 + vpsrld $25, %ymm4, %ymm4 + vpxor %ymm4, %ymm12, %ymm4 + vpslld $ 7, %ymm5, %ymm12 + vpsrld $25, %ymm5, %ymm5 + vpxor %ymm5, %ymm12, %ymm5 + vpxor %ymm6, %ymm10, %ymm6 + vpxor %ymm7, %ymm11, %ymm7 + vpslld $ 7, %ymm6, %ymm12 + vpsrld $25, %ymm6, %ymm6 + vpxor %ymm6, %ymm12, %ymm6 + vpslld $ 7, %ymm7, %ymm12 + vpsrld $25, %ymm7, %ymm7 + vpxor %ymm7, %ymm12, %ymm7 + vpaddd %ymm0, %ymm5, %ymm0 + vpaddd %ymm1, %ymm6, %ymm1 + vpxor %ymm15, %ymm0, %ymm15 + vpxor 96(%rsp), %ymm1, %ymm12 + vpaddd %ymm2, %ymm7, %ymm2 + vpaddd %ymm3, %ymm4, %ymm3 + vpxor %ymm13, %ymm2, %ymm13 + vpxor %ymm14, %ymm3, %ymm14 + vpshufb 448(%rsp), %ymm15, %ymm15 + vpshufb 448(%rsp), %ymm12, %ymm12 + vpaddd %ymm10, %ymm15, %ymm10 + vpaddd %ymm11, %ymm12, %ymm11 + vpshufb 448(%rsp), %ymm13, %ymm13 + vpshufb 448(%rsp), %ymm14, %ymm14 + vpaddd %ymm8, %ymm13, %ymm8 + vpaddd %ymm9, %ymm14, %ymm9 + vmovdqa %ymm15, 96(%rsp) + vpxor %ymm5, %ymm10, %ymm5 + vpxor %ymm6, %ymm11, %ymm6 + vpslld $ 12, %ymm5, %ymm15 + vpsrld $20, %ymm5, %ymm5 + vpxor %ymm5, %ymm15, %ymm5 + vpslld $ 12, %ymm6, %ymm15 + vpsrld $20, %ymm6, %ymm6 + vpxor %ymm6, %ymm15, %ymm6 + vpxor %ymm7, %ymm8, %ymm7 + vpxor %ymm4, %ymm9, %ymm4 + vpslld $ 12, %ymm7, %ymm15 + vpsrld $20, %ymm7, %ymm7 + vpxor %ymm7, %ymm15, %ymm7 + vpslld $ 12, %ymm4, %ymm15 + vpsrld $20, %ymm4, %ymm4 + vpxor %ymm4, %ymm15, %ymm4 + vpaddd %ymm0, %ymm5, %ymm0 + vpaddd %ymm1, %ymm6, %ymm1 + vpxor 96(%rsp), %ymm0, %ymm15 + vpxor %ymm12, %ymm1, %ymm12 + vpaddd %ymm2, %ymm7, %ymm2 + vpaddd %ymm3, %ymm4, %ymm3 + vpxor %ymm13, %ymm2, %ymm13 + vpxor %ymm14, %ymm3, %ymm14 + vpshufb 480(%rsp), %ymm15, %ymm15 + vpshufb 480(%rsp), %ymm12, %ymm12 + vpaddd %ymm10, %ymm15, %ymm10 + vpaddd %ymm11, %ymm12, %ymm11 + vpshufb 480(%rsp), %ymm13, %ymm13 + vpshufb 480(%rsp), %ymm14, %ymm14 + vpaddd %ymm8, %ymm13, %ymm8 + vpaddd %ymm9, %ymm14, %ymm9 + vmovdqa %ymm15, 96(%rsp) + vpxor %ymm5, %ymm10, %ymm5 + vpxor %ymm6, %ymm11, %ymm6 + vpslld $ 7, %ymm5, %ymm15 + vpsrld $25, %ymm5, %ymm5 + vpxor %ymm5, %ymm15, %ymm5 + vpslld $ 7, %ymm6, %ymm15 + vpsrld $25, %ymm6, %ymm6 + vpxor %ymm6, %ymm15, %ymm6 + vpxor %ymm7, %ymm8, %ymm7 + vpxor %ymm4, %ymm9, %ymm4 + vpslld $ 7, %ymm7, %ymm15 + vpsrld $25, %ymm7, %ymm7 + vpxor %ymm7, %ymm15, %ymm7 + vpslld $ 7, %ymm4, %ymm15 + vpsrld $25, %ymm4, %ymm4 + vpxor %ymm4, %ymm15, %ymm4 + vmovdqa 96(%rsp), %ymm15 + subq $2, %rax + jnz .Lchacha_blocks_avx2_mainloop1 + vmovdqa %ymm8, 192(%rsp) + vmovdqa %ymm9, 224(%rsp) + vmovdqa %ymm10, 256(%rsp) + vmovdqa %ymm11, 288(%rsp) + vmovdqa %ymm12, 320(%rsp) + vmovdqa %ymm13, 352(%rsp) + vmovdqa %ymm14, 384(%rsp) + vmovdqa %ymm15, 416(%rsp) + vpbroadcastd 0(%rsp), %ymm8 + vpbroadcastd 4+0(%rsp), %ymm9 + vpbroadcastd 8+0(%rsp), %ymm10 + vpbroadcastd 12+0(%rsp), %ymm11 + vpbroadcastd 16(%rsp), %ymm12 + vpbroadcastd 4+16(%rsp), %ymm13 + vpbroadcastd 8+16(%rsp), %ymm14 + vpbroadcastd 12+16(%rsp), %ymm15 + vpaddd %ymm8, %ymm0, %ymm0 + vpaddd %ymm9, %ymm1, %ymm1 + vpaddd %ymm10, %ymm2, %ymm2 + vpaddd %ymm11, %ymm3, %ymm3 + vpaddd %ymm12, %ymm4, %ymm4 + vpaddd %ymm13, %ymm5, %ymm5 + vpaddd %ymm14, %ymm6, %ymm6 + vpaddd %ymm15, %ymm7, %ymm7 + vpunpckldq %ymm1, %ymm0, %ymm8 + vpunpckldq %ymm3, %ymm2, %ymm9 + vpunpckhdq %ymm1, %ymm0, %ymm12 + vpunpckhdq %ymm3, %ymm2, %ymm13 + vpunpckldq %ymm5, %ymm4, %ymm10 + vpunpckldq %ymm7, %ymm6, %ymm11 + vpunpckhdq %ymm5, %ymm4, %ymm14 + vpunpckhdq %ymm7, %ymm6, %ymm15 + vpunpcklqdq %ymm9, %ymm8, %ymm0 + vpunpcklqdq %ymm11, %ymm10, %ymm1 + vpunpckhqdq %ymm9, %ymm8, %ymm2 + vpunpckhqdq %ymm11, %ymm10, %ymm3 + vpunpcklqdq %ymm13, %ymm12, %ymm4 + vpunpcklqdq %ymm15, %ymm14, %ymm5 + vpunpckhqdq %ymm13, %ymm12, %ymm6 + vpunpckhqdq %ymm15, %ymm14, %ymm7 + vperm2i128 $0x20, %ymm1, %ymm0, %ymm8 + vperm2i128 $0x20, %ymm3, %ymm2, %ymm9 + vperm2i128 $0x31, %ymm1, %ymm0, %ymm12 + vperm2i128 $0x31, %ymm3, %ymm2, %ymm13 + vperm2i128 $0x20, %ymm5, %ymm4, %ymm10 + vperm2i128 $0x20, %ymm7, %ymm6, %ymm11 + vperm2i128 $0x31, %ymm5, %ymm4, %ymm14 + vperm2i128 $0x31, %ymm7, %ymm6, %ymm15 + andq %rsi, %rsi + jz .Lchacha_blocks_avx2_noinput1 + vpxor 0(%rsi), %ymm8, %ymm8 + vpxor 64(%rsi), %ymm9, %ymm9 + vpxor 128(%rsi), %ymm10, %ymm10 + vpxor 192(%rsi), %ymm11, %ymm11 + vpxor 256(%rsi), %ymm12, %ymm12 + vpxor 320(%rsi), %ymm13, %ymm13 + vpxor 384(%rsi), %ymm14, %ymm14 + vpxor 448(%rsi), %ymm15, %ymm15 + vmovdqu %ymm8, 0(%rdx) + vmovdqu %ymm9, 64(%rdx) + vmovdqu %ymm10, 128(%rdx) + vmovdqu %ymm11, 192(%rdx) + vmovdqu %ymm12, 256(%rdx) + vmovdqu %ymm13, 320(%rdx) + vmovdqu %ymm14, 384(%rdx) + vmovdqu %ymm15, 448(%rdx) + vmovdqa 192(%rsp), %ymm0 + vmovdqa 224(%rsp), %ymm1 + vmovdqa 256(%rsp), %ymm2 + vmovdqa 288(%rsp), %ymm3 + vmovdqa 320(%rsp), %ymm4 + vmovdqa 352(%rsp), %ymm5 + vmovdqa 384(%rsp), %ymm6 + vmovdqa 416(%rsp), %ymm7 + vpbroadcastd 32(%rsp), %ymm8 + vpbroadcastd 4+32(%rsp), %ymm9 + vpbroadcastd 8+32(%rsp), %ymm10 + vpbroadcastd 12+32(%rsp), %ymm11 + vmovdqa 128(%rsp), %ymm12 + vmovdqa 160(%rsp), %ymm13 + vpbroadcastd 8+48(%rsp), %ymm14 + vpbroadcastd 12+48(%rsp), %ymm15 + vpaddd %ymm8, %ymm0, %ymm0 + vpaddd %ymm9, %ymm1, %ymm1 + vpaddd %ymm10, %ymm2, %ymm2 + vpaddd %ymm11, %ymm3, %ymm3 + vpaddd %ymm12, %ymm4, %ymm4 + vpaddd %ymm13, %ymm5, %ymm5 + vpaddd %ymm14, %ymm6, %ymm6 + vpaddd %ymm15, %ymm7, %ymm7 + vpunpckldq %ymm1, %ymm0, %ymm8 + vpunpckldq %ymm3, %ymm2, %ymm9 + vpunpckhdq %ymm1, %ymm0, %ymm12 + vpunpckhdq %ymm3, %ymm2, %ymm13 + vpunpckldq %ymm5, %ymm4, %ymm10 + vpunpckldq %ymm7, %ymm6, %ymm11 + vpunpckhdq %ymm5, %ymm4, %ymm14 + vpunpckhdq %ymm7, %ymm6, %ymm15 + vpunpcklqdq %ymm9, %ymm8, %ymm0 + vpunpcklqdq %ymm11, %ymm10, %ymm1 + vpunpckhqdq %ymm9, %ymm8, %ymm2 + vpunpckhqdq %ymm11, %ymm10, %ymm3 + vpunpcklqdq %ymm13, %ymm12, %ymm4 + vpunpcklqdq %ymm15, %ymm14, %ymm5 + vpunpckhqdq %ymm13, %ymm12, %ymm6 + vpunpckhqdq %ymm15, %ymm14, %ymm7 + vperm2i128 $0x20, %ymm1, %ymm0, %ymm8 + vperm2i128 $0x20, %ymm3, %ymm2, %ymm9 + vperm2i128 $0x31, %ymm1, %ymm0, %ymm12 + vperm2i128 $0x31, %ymm3, %ymm2, %ymm13 + vperm2i128 $0x20, %ymm5, %ymm4, %ymm10 + vperm2i128 $0x20, %ymm7, %ymm6, %ymm11 + vperm2i128 $0x31, %ymm5, %ymm4, %ymm14 + vperm2i128 $0x31, %ymm7, %ymm6, %ymm15 + vpxor 32(%rsi), %ymm8, %ymm8 + vpxor 96(%rsi), %ymm9, %ymm9 + vpxor 160(%rsi), %ymm10, %ymm10 + vpxor 224(%rsi), %ymm11, %ymm11 + vpxor 288(%rsi), %ymm12, %ymm12 + vpxor 352(%rsi), %ymm13, %ymm13 + vpxor 416(%rsi), %ymm14, %ymm14 + vpxor 480(%rsi), %ymm15, %ymm15 + vmovdqu %ymm8, 32(%rdx) + vmovdqu %ymm9, 96(%rdx) + vmovdqu %ymm10, 160(%rdx) + vmovdqu %ymm11, 224(%rdx) + vmovdqu %ymm12, 288(%rdx) + vmovdqu %ymm13, 352(%rdx) + vmovdqu %ymm14, 416(%rdx) + vmovdqu %ymm15, 480(%rdx) + addq $512, %rsi + jmp .Lchacha_blocks_avx2_mainloop1_cont +.Lchacha_blocks_avx2_noinput1: + vmovdqu %ymm8, 0(%rdx) + vmovdqu %ymm9, 64(%rdx) + vmovdqu %ymm10, 128(%rdx) + vmovdqu %ymm11, 192(%rdx) + vmovdqu %ymm12, 256(%rdx) + vmovdqu %ymm13, 320(%rdx) + vmovdqu %ymm14, 384(%rdx) + vmovdqu %ymm15, 448(%rdx) + vmovdqa 192(%rsp), %ymm0 + vmovdqa 224(%rsp), %ymm1 + vmovdqa 256(%rsp), %ymm2 + vmovdqa 288(%rsp), %ymm3 + vmovdqa 320(%rsp), %ymm4 + vmovdqa 352(%rsp), %ymm5 + vmovdqa 384(%rsp), %ymm6 + vmovdqa 416(%rsp), %ymm7 + vpbroadcastd 32(%rsp), %ymm8 + vpbroadcastd 4+32(%rsp), %ymm9 + vpbroadcastd 8+32(%rsp), %ymm10 + vpbroadcastd 12+32(%rsp), %ymm11 + vmovdqa 128(%rsp), %ymm12 + vmovdqa 160(%rsp), %ymm13 + vpbroadcastd 8+48(%rsp), %ymm14 + vpbroadcastd 12+48(%rsp), %ymm15 + vpaddd %ymm8, %ymm0, %ymm0 + vpaddd %ymm9, %ymm1, %ymm1 + vpaddd %ymm10, %ymm2, %ymm2 + vpaddd %ymm11, %ymm3, %ymm3 + vpaddd %ymm12, %ymm4, %ymm4 + vpaddd %ymm13, %ymm5, %ymm5 + vpaddd %ymm14, %ymm6, %ymm6 + vpaddd %ymm15, %ymm7, %ymm7 + vpunpckldq %ymm1, %ymm0, %ymm8 + vpunpckldq %ymm3, %ymm2, %ymm9 + vpunpckhdq %ymm1, %ymm0, %ymm12 + vpunpckhdq %ymm3, %ymm2, %ymm13 + vpunpckldq %ymm5, %ymm4, %ymm10 + vpunpckldq %ymm7, %ymm6, %ymm11 + vpunpckhdq %ymm5, %ymm4, %ymm14 + vpunpckhdq %ymm7, %ymm6, %ymm15 + vpunpcklqdq %ymm9, %ymm8, %ymm0 + vpunpcklqdq %ymm11, %ymm10, %ymm1 + vpunpckhqdq %ymm9, %ymm8, %ymm2 + vpunpckhqdq %ymm11, %ymm10, %ymm3 + vpunpcklqdq %ymm13, %ymm12, %ymm4 + vpunpcklqdq %ymm15, %ymm14, %ymm5 + vpunpckhqdq %ymm13, %ymm12, %ymm6 + vpunpckhqdq %ymm15, %ymm14, %ymm7 + vperm2i128 $0x20, %ymm1, %ymm0, %ymm8 + vperm2i128 $0x20, %ymm3, %ymm2, %ymm9 + vperm2i128 $0x31, %ymm1, %ymm0, %ymm12 + vperm2i128 $0x31, %ymm3, %ymm2, %ymm13 + vperm2i128 $0x20, %ymm5, %ymm4, %ymm10 + vperm2i128 $0x20, %ymm7, %ymm6, %ymm11 + vperm2i128 $0x31, %ymm5, %ymm4, %ymm14 + vperm2i128 $0x31, %ymm7, %ymm6, %ymm15 + vmovdqu %ymm8, 32(%rdx) + vmovdqu %ymm9, 96(%rdx) + vmovdqu %ymm10, 160(%rdx) + vmovdqu %ymm11, 224(%rdx) + vmovdqu %ymm12, 288(%rdx) + vmovdqu %ymm13, 352(%rdx) + vmovdqu %ymm14, 416(%rdx) + vmovdqu %ymm15, 480(%rdx) +.Lchacha_blocks_avx2_mainloop1_cont: + addq $512, %rdx + subq $512, %rcx + cmp $512, %rcx + jae .Lchacha_blocks_avx2_atleast512 + cmp $256, %rcx + jb .Lchacha_blocks_avx2_below256_fixup +.Lchacha_blocks_avx2_atleast256: + movq 48(%rsp), %rax + leaq 1(%rax), %r8 + leaq 2(%rax), %r9 + leaq 3(%rax), %r10 + leaq 4(%rax), %rbx + movl %eax, 128(%rsp) + movl %r8d, 4+128(%rsp) + movl %r9d, 8+128(%rsp) + movl %r10d, 12+128(%rsp) + shrq $32, %rax + shrq $32, %r8 + shrq $32, %r9 + shrq $32, %r10 + movl %eax, 160(%rsp) + movl %r8d, 4+160(%rsp) + movl %r9d, 8+160(%rsp) + movl %r10d, 12+160(%rsp) + movq %rbx, 48(%rsp) + movq 64(%rsp), %rax + vpbroadcastd 0(%rsp), %xmm0 + vpbroadcastd 4+0(%rsp), %xmm1 + vpbroadcastd 8+0(%rsp), %xmm2 + vpbroadcastd 12+0(%rsp), %xmm3 + vpbroadcastd 16(%rsp), %xmm4 + vpbroadcastd 4+16(%rsp), %xmm5 + vpbroadcastd 8+16(%rsp), %xmm6 + vpbroadcastd 12+16(%rsp), %xmm7 + vpbroadcastd 32(%rsp), %xmm8 + vpbroadcastd 4+32(%rsp), %xmm9 + vpbroadcastd 8+32(%rsp), %xmm10 + vpbroadcastd 12+32(%rsp), %xmm11 + vmovdqa 128(%rsp), %xmm12 + vmovdqa 160(%rsp), %xmm13 + vpbroadcastd 8+48(%rsp), %xmm14 + vpbroadcastd 12+48(%rsp), %xmm15 +.Lchacha_blocks_avx2_mainloop2: + vpaddd %xmm0, %xmm4, %xmm0 + vpaddd %xmm1, %xmm5, %xmm1 + vpxor %xmm12, %xmm0, %xmm12 + vpxor %xmm13, %xmm1, %xmm13 + vpaddd %xmm2, %xmm6, %xmm2 + vpaddd %xmm3, %xmm7, %xmm3 + vpxor %xmm14, %xmm2, %xmm14 + vpxor %xmm15, %xmm3, %xmm15 + vpshufb 448(%rsp), %xmm12, %xmm12 + vpshufb 448(%rsp), %xmm13, %xmm13 + vpaddd %xmm8, %xmm12, %xmm8 + vpaddd %xmm9, %xmm13, %xmm9 + vpshufb 448(%rsp), %xmm14, %xmm14 + vpshufb 448(%rsp), %xmm15, %xmm15 + vpaddd %xmm10, %xmm14, %xmm10 + vpaddd %xmm11, %xmm15, %xmm11 + vmovdqa %xmm12, 96(%rsp) + vpxor %xmm4, %xmm8, %xmm4 + vpxor %xmm5, %xmm9, %xmm5 + vpslld $ 12, %xmm4, %xmm12 + vpsrld $20, %xmm4, %xmm4 + vpxor %xmm4, %xmm12, %xmm4 + vpslld $ 12, %xmm5, %xmm12 + vpsrld $20, %xmm5, %xmm5 + vpxor %xmm5, %xmm12, %xmm5 + vpxor %xmm6, %xmm10, %xmm6 + vpxor %xmm7, %xmm11, %xmm7 + vpslld $ 12, %xmm6, %xmm12 + vpsrld $20, %xmm6, %xmm6 + vpxor %xmm6, %xmm12, %xmm6 + vpslld $ 12, %xmm7, %xmm12 + vpsrld $20, %xmm7, %xmm7 + vpxor %xmm7, %xmm12, %xmm7 + vpaddd %xmm0, %xmm4, %xmm0 + vpaddd %xmm1, %xmm5, %xmm1 + vpxor 96(%rsp), %xmm0, %xmm12 + vpxor %xmm13, %xmm1, %xmm13 + vpaddd %xmm2, %xmm6, %xmm2 + vpaddd %xmm3, %xmm7, %xmm3 + vpxor %xmm14, %xmm2, %xmm14 + vpxor %xmm15, %xmm3, %xmm15 + vpshufb 480(%rsp), %xmm12, %xmm12 + vpshufb 480(%rsp), %xmm13, %xmm13 + vpaddd %xmm8, %xmm12, %xmm8 + vpaddd %xmm9, %xmm13, %xmm9 + vpshufb 480(%rsp), %xmm14, %xmm14 + vpshufb 480(%rsp), %xmm15, %xmm15 + vpaddd %xmm10, %xmm14, %xmm10 + vpaddd %xmm11, %xmm15, %xmm11 + vmovdqa %xmm12, 96(%rsp) + vpxor %xmm4, %xmm8, %xmm4 + vpxor %xmm5, %xmm9, %xmm5 + vpslld $ 7, %xmm4, %xmm12 + vpsrld $25, %xmm4, %xmm4 + vpxor %xmm4, %xmm12, %xmm4 + vpslld $ 7, %xmm5, %xmm12 + vpsrld $25, %xmm5, %xmm5 + vpxor %xmm5, %xmm12, %xmm5 + vpxor %xmm6, %xmm10, %xmm6 + vpxor %xmm7, %xmm11, %xmm7 + vpslld $ 7, %xmm6, %xmm12 + vpsrld $25, %xmm6, %xmm6 + vpxor %xmm6, %xmm12, %xmm6 + vpslld $ 7, %xmm7, %xmm12 + vpsrld $25, %xmm7, %xmm7 + vpxor %xmm7, %xmm12, %xmm7 + vpaddd %xmm0, %xmm5, %xmm0 + vpaddd %xmm1, %xmm6, %xmm1 + vpxor %xmm15, %xmm0, %xmm15 + vpxor 96(%rsp), %xmm1, %xmm12 + vpaddd %xmm2, %xmm7, %xmm2 + vpaddd %xmm3, %xmm4, %xmm3 + vpxor %xmm13, %xmm2, %xmm13 + vpxor %xmm14, %xmm3, %xmm14 + vpshufb 448(%rsp), %xmm15, %xmm15 + vpshufb 448(%rsp), %xmm12, %xmm12 + vpaddd %xmm10, %xmm15, %xmm10 + vpaddd %xmm11, %xmm12, %xmm11 + vpshufb 448(%rsp), %xmm13, %xmm13 + vpshufb 448(%rsp), %xmm14, %xmm14 + vpaddd %xmm8, %xmm13, %xmm8 + vpaddd %xmm9, %xmm14, %xmm9 + vmovdqa %xmm15, 96(%rsp) + vpxor %xmm5, %xmm10, %xmm5 + vpxor %xmm6, %xmm11, %xmm6 + vpslld $ 12, %xmm5, %xmm15 + vpsrld $20, %xmm5, %xmm5 + vpxor %xmm5, %xmm15, %xmm5 + vpslld $ 12, %xmm6, %xmm15 + vpsrld $20, %xmm6, %xmm6 + vpxor %xmm6, %xmm15, %xmm6 + vpxor %xmm7, %xmm8, %xmm7 + vpxor %xmm4, %xmm9, %xmm4 + vpslld $ 12, %xmm7, %xmm15 + vpsrld $20, %xmm7, %xmm7 + vpxor %xmm7, %xmm15, %xmm7 + vpslld $ 12, %xmm4, %xmm15 + vpsrld $20, %xmm4, %xmm4 + vpxor %xmm4, %xmm15, %xmm4 + vpaddd %xmm0, %xmm5, %xmm0 + vpaddd %xmm1, %xmm6, %xmm1 + vpxor 96(%rsp), %xmm0, %xmm15 + vpxor %xmm12, %xmm1, %xmm12 + vpaddd %xmm2, %xmm7, %xmm2 + vpaddd %xmm3, %xmm4, %xmm3 + vpxor %xmm13, %xmm2, %xmm13 + vpxor %xmm14, %xmm3, %xmm14 + vpshufb 480(%rsp), %xmm15, %xmm15 + vpshufb 480(%rsp), %xmm12, %xmm12 + vpaddd %xmm10, %xmm15, %xmm10 + vpaddd %xmm11, %xmm12, %xmm11 + vpshufb 480(%rsp), %xmm13, %xmm13 + vpshufb 480(%rsp), %xmm14, %xmm14 + vpaddd %xmm8, %xmm13, %xmm8 + vpaddd %xmm9, %xmm14, %xmm9 + vmovdqa %xmm15, 96(%rsp) + vpxor %xmm5, %xmm10, %xmm5 + vpxor %xmm6, %xmm11, %xmm6 + vpslld $ 7, %xmm5, %xmm15 + vpsrld $25, %xmm5, %xmm5 + vpxor %xmm5, %xmm15, %xmm5 + vpslld $ 7, %xmm6, %xmm15 + vpsrld $25, %xmm6, %xmm6 + vpxor %xmm6, %xmm15, %xmm6 + vpxor %xmm7, %xmm8, %xmm7 + vpxor %xmm4, %xmm9, %xmm4 + vpslld $ 7, %xmm7, %xmm15 + vpsrld $25, %xmm7, %xmm7 + vpxor %xmm7, %xmm15, %xmm7 + vpslld $ 7, %xmm4, %xmm15 + vpsrld $25, %xmm4, %xmm4 + vpxor %xmm4, %xmm15, %xmm4 + vmovdqa 96(%rsp), %xmm15 + subq $2, %rax + jnz .Lchacha_blocks_avx2_mainloop2 + vmovdqa %xmm8, 192(%rsp) + vmovdqa %xmm9, 208(%rsp) + vmovdqa %xmm10, 224(%rsp) + vmovdqa %xmm11, 240(%rsp) + vmovdqa %xmm12, 256(%rsp) + vmovdqa %xmm13, 272(%rsp) + vmovdqa %xmm14, 288(%rsp) + vmovdqa %xmm15, 304(%rsp) + vpbroadcastd 0(%rsp), %xmm8 + vpbroadcastd 4+0(%rsp), %xmm9 + vpbroadcastd 8+0(%rsp), %xmm10 + vpbroadcastd 12+0(%rsp), %xmm11 + vpbroadcastd 16(%rsp), %xmm12 + vpbroadcastd 4+16(%rsp), %xmm13 + vpbroadcastd 8+16(%rsp), %xmm14 + vpbroadcastd 12+16(%rsp), %xmm15 + vpaddd %xmm8, %xmm0, %xmm0 + vpaddd %xmm9, %xmm1, %xmm1 + vpaddd %xmm10, %xmm2, %xmm2 + vpaddd %xmm11, %xmm3, %xmm3 + vpaddd %xmm12, %xmm4, %xmm4 + vpaddd %xmm13, %xmm5, %xmm5 + vpaddd %xmm14, %xmm6, %xmm6 + vpaddd %xmm15, %xmm7, %xmm7 + vpunpckldq %xmm1, %xmm0, %xmm8 + vpunpckldq %xmm3, %xmm2, %xmm9 + vpunpckhdq %xmm1, %xmm0, %xmm12 + vpunpckhdq %xmm3, %xmm2, %xmm13 + vpunpckldq %xmm5, %xmm4, %xmm10 + vpunpckldq %xmm7, %xmm6, %xmm11 + vpunpckhdq %xmm5, %xmm4, %xmm14 + vpunpckhdq %xmm7, %xmm6, %xmm15 + vpunpcklqdq %xmm9, %xmm8, %xmm0 + vpunpcklqdq %xmm11, %xmm10, %xmm1 + vpunpckhqdq %xmm9, %xmm8, %xmm2 + vpunpckhqdq %xmm11, %xmm10, %xmm3 + vpunpcklqdq %xmm13, %xmm12, %xmm4 + vpunpcklqdq %xmm15, %xmm14, %xmm5 + vpunpckhqdq %xmm13, %xmm12, %xmm6 + vpunpckhqdq %xmm15, %xmm14, %xmm7 + andq %rsi, %rsi + jz .Lchacha_blocks_avx2_noinput2 + vpxor 0(%rsi), %xmm0, %xmm0 + vpxor 16(%rsi), %xmm1, %xmm1 + vpxor 64(%rsi), %xmm2, %xmm2 + vpxor 80(%rsi), %xmm3, %xmm3 + vpxor 128(%rsi), %xmm4, %xmm4 + vpxor 144(%rsi), %xmm5, %xmm5 + vpxor 192(%rsi), %xmm6, %xmm6 + vpxor 208(%rsi), %xmm7, %xmm7 + vmovdqu %xmm0, 0(%rdx) + vmovdqu %xmm1, 16(%rdx) + vmovdqu %xmm2, 64(%rdx) + vmovdqu %xmm3, 80(%rdx) + vmovdqu %xmm4, 128(%rdx) + vmovdqu %xmm5, 144(%rdx) + vmovdqu %xmm6, 192(%rdx) + vmovdqu %xmm7, 208(%rdx) + vmovdqa 192(%rsp), %xmm0 + vmovdqa 208(%rsp), %xmm1 + vmovdqa 224(%rsp), %xmm2 + vmovdqa 240(%rsp), %xmm3 + vmovdqa 256(%rsp), %xmm4 + vmovdqa 272(%rsp), %xmm5 + vmovdqa 288(%rsp), %xmm6 + vmovdqa 304(%rsp), %xmm7 + vpbroadcastd 32(%rsp), %xmm8 + vpbroadcastd 4+32(%rsp), %xmm9 + vpbroadcastd 8+32(%rsp), %xmm10 + vpbroadcastd 12+32(%rsp), %xmm11 + vmovdqa 128(%rsp), %xmm12 + vmovdqa 160(%rsp), %xmm13 + vpbroadcastd 8+48(%rsp), %xmm14 + vpbroadcastd 12+48(%rsp), %xmm15 + vpaddd %xmm8, %xmm0, %xmm0 + vpaddd %xmm9, %xmm1, %xmm1 + vpaddd %xmm10, %xmm2, %xmm2 + vpaddd %xmm11, %xmm3, %xmm3 + vpaddd %xmm12, %xmm4, %xmm4 + vpaddd %xmm13, %xmm5, %xmm5 + vpaddd %xmm14, %xmm6, %xmm6 + vpaddd %xmm15, %xmm7, %xmm7 + vpunpckldq %xmm1, %xmm0, %xmm8 + vpunpckldq %xmm3, %xmm2, %xmm9 + vpunpckhdq %xmm1, %xmm0, %xmm12 + vpunpckhdq %xmm3, %xmm2, %xmm13 + vpunpckldq %xmm5, %xmm4, %xmm10 + vpunpckldq %xmm7, %xmm6, %xmm11 + vpunpckhdq %xmm5, %xmm4, %xmm14 + vpunpckhdq %xmm7, %xmm6, %xmm15 + vpunpcklqdq %xmm9, %xmm8, %xmm0 + vpunpcklqdq %xmm11, %xmm10, %xmm1 + vpunpckhqdq %xmm9, %xmm8, %xmm2 + vpunpckhqdq %xmm11, %xmm10, %xmm3 + vpunpcklqdq %xmm13, %xmm12, %xmm4 + vpunpcklqdq %xmm15, %xmm14, %xmm5 + vpunpckhqdq %xmm13, %xmm12, %xmm6 + vpunpckhqdq %xmm15, %xmm14, %xmm7 + vpxor 32(%rsi), %xmm0, %xmm0 + vpxor 48(%rsi), %xmm1, %xmm1 + vpxor 96(%rsi), %xmm2, %xmm2 + vpxor 112(%rsi), %xmm3, %xmm3 + vpxor 160(%rsi), %xmm4, %xmm4 + vpxor 176(%rsi), %xmm5, %xmm5 + vpxor 224(%rsi), %xmm6, %xmm6 + vpxor 240(%rsi), %xmm7, %xmm7 + vmovdqu %xmm0, 32(%rdx) + vmovdqu %xmm1, 48(%rdx) + vmovdqu %xmm2, 96(%rdx) + vmovdqu %xmm3, 112(%rdx) + vmovdqu %xmm4, 160(%rdx) + vmovdqu %xmm5, 176(%rdx) + vmovdqu %xmm6, 224(%rdx) + vmovdqu %xmm7, 240(%rdx) + addq $256, %rsi + jmp .Lchacha_blocks_avx2_mainloop2_cont +.Lchacha_blocks_avx2_noinput2: + vmovdqu %xmm0, 0(%rdx) + vmovdqu %xmm1, 16(%rdx) + vmovdqu %xmm2, 64(%rdx) + vmovdqu %xmm3, 80(%rdx) + vmovdqu %xmm4, 128(%rdx) + vmovdqu %xmm5, 144(%rdx) + vmovdqu %xmm6, 192(%rdx) + vmovdqu %xmm7, 208(%rdx) + vmovdqa 192(%rsp), %xmm0 + vmovdqa 208(%rsp), %xmm1 + vmovdqa 224(%rsp), %xmm2 + vmovdqa 240(%rsp), %xmm3 + vmovdqa 256(%rsp), %xmm4 + vmovdqa 272(%rsp), %xmm5 + vmovdqa 288(%rsp), %xmm6 + vmovdqa 304(%rsp), %xmm7 + vpbroadcastd 32(%rsp), %xmm8 + vpbroadcastd 4+32(%rsp), %xmm9 + vpbroadcastd 8+32(%rsp), %xmm10 + vpbroadcastd 12+32(%rsp), %xmm11 + vmovdqa 128(%rsp), %xmm12 + vmovdqa 160(%rsp), %xmm13 + vpbroadcastd 8+48(%rsp), %xmm14 + vpbroadcastd 12+48(%rsp), %xmm15 + vpaddd %xmm8, %xmm0, %xmm0 + vpaddd %xmm9, %xmm1, %xmm1 + vpaddd %xmm10, %xmm2, %xmm2 + vpaddd %xmm11, %xmm3, %xmm3 + vpaddd %xmm12, %xmm4, %xmm4 + vpaddd %xmm13, %xmm5, %xmm5 + vpaddd %xmm14, %xmm6, %xmm6 + vpaddd %xmm15, %xmm7, %xmm7 + vpunpckldq %xmm1, %xmm0, %xmm8 + vpunpckldq %xmm3, %xmm2, %xmm9 + vpunpckhdq %xmm1, %xmm0, %xmm12 + vpunpckhdq %xmm3, %xmm2, %xmm13 + vpunpckldq %xmm5, %xmm4, %xmm10 + vpunpckldq %xmm7, %xmm6, %xmm11 + vpunpckhdq %xmm5, %xmm4, %xmm14 + vpunpckhdq %xmm7, %xmm6, %xmm15 + vpunpcklqdq %xmm9, %xmm8, %xmm0 + vpunpcklqdq %xmm11, %xmm10, %xmm1 + vpunpckhqdq %xmm9, %xmm8, %xmm2 + vpunpckhqdq %xmm11, %xmm10, %xmm3 + vpunpcklqdq %xmm13, %xmm12, %xmm4 + vpunpcklqdq %xmm15, %xmm14, %xmm5 + vpunpckhqdq %xmm13, %xmm12, %xmm6 + vpunpckhqdq %xmm15, %xmm14, %xmm7 + vmovdqu %xmm0, 32(%rdx) + vmovdqu %xmm1, 48(%rdx) + vmovdqu %xmm2, 96(%rdx) + vmovdqu %xmm3, 112(%rdx) + vmovdqu %xmm4, 160(%rdx) + vmovdqu %xmm5, 176(%rdx) + vmovdqu %xmm6, 224(%rdx) + vmovdqu %xmm7, 240(%rdx) +.Lchacha_blocks_avx2_mainloop2_cont: + addq $256, %rdx + subq $256, %rcx + cmp $256, %rcx + jae .Lchacha_blocks_avx2_atleast256 +.Lchacha_blocks_avx2_below256_fixup: + vmovdqa 448(%rsp), %xmm6 + vmovdqa 480(%rsp), %xmm7 + vmovdqa 0(%rsp), %xmm8 + vmovdqa 16(%rsp), %xmm9 + vmovdqa 32(%rsp), %xmm10 + vmovdqa 48(%rsp), %xmm11 + movq $1, %r9 +.Lchacha_blocks_avx2_below256: + vmovq %r9, %xmm5 + andq %rcx, %rcx + jz .Lchacha_blocks_avx2_done + cmpq $64, %rcx + jae .Lchacha_blocks_avx2_above63 + movq %rdx, %r9 + andq %rsi, %rsi + jz .Lchacha_blocks_avx2_noinput3 + movq %rcx, %r10 + movq %rsp, %rdx + addq %r10, %rsi + addq %r10, %rdx + negq %r10 +.Lchacha_blocks_avx2_copyinput: + movb (%rsi, %r10), %al + movb %al, (%rdx, %r10) + incq %r10 + jnz .Lchacha_blocks_avx2_copyinput + movq %rsp, %rsi +.Lchacha_blocks_avx2_noinput3: + movq %rsp, %rdx +.Lchacha_blocks_avx2_above63: + vmovdqa %xmm8, %xmm0 + vmovdqa %xmm9, %xmm1 + vmovdqa %xmm10, %xmm2 + vmovdqa %xmm11, %xmm3 + movq 64(%rsp), %rax +.Lchacha_blocks_avx2_mainloop3: + vpaddd %xmm0, %xmm1, %xmm0 + vpxor %xmm3, %xmm0, %xmm3 + vpshufb %xmm6, %xmm3, %xmm3 + vpaddd %xmm2, %xmm3, %xmm2 + vpxor %xmm1, %xmm2, %xmm1 + vpslld $12, %xmm1, %xmm4 + vpsrld $20, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm1 + vpaddd %xmm0, %xmm1, %xmm0 + vpxor %xmm3, %xmm0, %xmm3 + vpshufb %xmm7, %xmm3, %xmm3 + vpshufd $0x93, %xmm0, %xmm0 + vpaddd %xmm2, %xmm3, %xmm2 + vpshufd $0x4e, %xmm3, %xmm3 + vpxor %xmm1, %xmm2, %xmm1 + vpshufd $0x39, %xmm2, %xmm2 + vpslld $7, %xmm1, %xmm4 + vpsrld $25, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm1 + vpaddd %xmm0, %xmm1, %xmm0 + vpxor %xmm3, %xmm0, %xmm3 + vpshufb %xmm6, %xmm3, %xmm3 + vpaddd %xmm2, %xmm3, %xmm2 + vpxor %xmm1, %xmm2, %xmm1 + vpslld $12, %xmm1, %xmm4 + vpsrld $20, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm1 + vpaddd %xmm0, %xmm1, %xmm0 + vpxor %xmm3, %xmm0, %xmm3 + vpshufb %xmm7, %xmm3, %xmm3 + vpshufd $0x39, %xmm0, %xmm0 + vpaddd %xmm2, %xmm3, %xmm2 + vpshufd $0x4e, %xmm3, %xmm3 + vpxor %xmm1, %xmm2, %xmm1 + vpshufd $0x93, %xmm2, %xmm2 + vpslld $7, %xmm1, %xmm4 + vpsrld $25, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm1 + subq $2, %rax + jnz .Lchacha_blocks_avx2_mainloop3 + vpaddd %xmm0, %xmm8, %xmm0 + vpaddd %xmm1, %xmm9, %xmm1 + vpaddd %xmm2, %xmm10, %xmm2 + vpaddd %xmm3, %xmm11, %xmm3 + andq %rsi, %rsi + jz .Lchacha_blocks_avx2_noinput4 + vpxor 0(%rsi), %xmm0, %xmm0 + vpxor 16(%rsi), %xmm1, %xmm1 + vpxor 32(%rsi), %xmm2, %xmm2 + vpxor 48(%rsi), %xmm3, %xmm3 + addq $64, %rsi +.Lchacha_blocks_avx2_noinput4: + vmovdqu %xmm0, 0(%rdx) + vmovdqu %xmm1, 16(%rdx) + vmovdqu %xmm2, 32(%rdx) + vmovdqu %xmm3, 48(%rdx) + vpaddq %xmm11, %xmm5, %xmm11 + cmpq $64, %rcx + jbe .Lchacha_blocks_avx2_mainloop3_finishup + addq $64, %rdx + subq $64, %rcx + jmp .Lchacha_blocks_avx2_below256 +.Lchacha_blocks_avx2_mainloop3_finishup: + cmpq $64, %rcx + je .Lchacha_blocks_avx2_done + addq %rcx, %r9 + addq %rcx, %rdx + negq %rcx +.Lchacha_blocks_avx2_copyoutput: + movb (%rdx, %rcx), %al + movb %al, (%r9, %rcx) + incq %rcx + jnz .Lchacha_blocks_avx2_copyoutput +.Lchacha_blocks_avx2_done: + vmovdqu %xmm11, 48(%rdi) + movq %rbp, %rsp + popq %r14 + popq %r13 + popq %r12 + popq %rbp + popq %rbx + vzeroall + movl $(63 + 512), %eax + ret +.size _gcry_chacha20_amd64_avx2_blocks,.-_gcry_chacha20_amd64_avx2_blocks; + +.data +.align 16 +.LC: +.byte 2,3,0,1,6,7,4,5,10,11,8,9,14,15,12,13 /* pshufb rotate by 16 */ +.byte 3,0,1,2,7,4,5,6,11,8,9,10,15,12,13,14 /* pshufb rotate by 8 */ + +#endif /*defined(USE_CHACHA20)*/ +#endif /*__x86_64*/ diff --git a/cipher/chacha20.c b/cipher/chacha20.c index de8982b..2ac5a32 100644 --- a/cipher/chacha20.c +++ b/cipher/chacha20.c @@ -54,6 +54,13 @@ # define USE_SSSE3 1 #endif +/* USE_AVX2 indicates whether to compile with Intel AVX2 code. */ +#undef USE_AVX2 +#if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) && \ + defined(HAVE_GCC_INLINE_ASM_AVX2) +# define USE_AVX2 1 +#endif + struct CHACHA20_context_s; @@ -77,6 +84,13 @@ unsigned int _gcry_chacha20_amd64_ssse3_blocks(u32 *state, const byte *in, #endif /* USE_SSSE3 */ +#ifdef USE_AVX2 + +unsigned int _gcry_chacha20_amd64_avx2_blocks(u32 *state, const byte *in, + byte *out, size_t bytes); + +#endif /* USE_AVX2 */ + static void chacha20_setiv (void *context, const byte * iv, size_t ivlen); static const char *selftest (void); @@ -314,6 +328,10 @@ chacha20_do_setkey (CHACHA20_context_t * ctx, if (features & HWF_INTEL_SSSE3) ctx->blocks = _gcry_chacha20_amd64_ssse3_blocks; #endif +#ifdef USE_AVX2 + if (features & HWF_INTEL_AVX2) + ctx->blocks = _gcry_chacha20_amd64_avx2_blocks; +#endif (void)features; @@ -422,7 +440,7 @@ selftest (void) { CHACHA20_context_t ctx; byte scratch[127 + 1]; - byte buf[256 + 64 + 4]; + byte buf[512 + 64 + 4]; int i; /* From draft-strombergson-chacha-test-vectors */ diff --git a/configure.ac b/configure.ac index 0342067..3a0fd52 100644 --- a/configure.ac +++ b/configure.ac @@ -1816,6 +1816,7 @@ if test "$found" = "1" ; then x86_64-*-*) # Build with the assembly implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-ssse3-amd64.lo" + GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-avx2-amd64.lo" ;; esac fi commit def7d4cad386271c6d4e2f10aabe0cb4abd871e4 Author: Jussi Kivilinna Date: Sun May 11 12:00:19 2014 +0300 chacha20: add SSSE3 assembly implementation * cipher/Makefile.am: Add 'chacha20-ssse3-amd64.S'. * cipher/chacha20-ssse3-amd64.S: New. * cipher/chacha20.c (USE_SSSE3): New macro. [USE_SSSE3] (_gcry_chacha20_amd64_ssse3_blocks): New. (chacha20_do_setkey): Select SSSE3 implementation if there is HW support. * configure.ac [host=x86-64]: Add 'chacha20-ssse3-amd64.lo'. -- Add SSSE3 optimized implementation for ChaCha20. Based on implementation by Andrew Moon. Before (Intel Haswell): CHACHA20 | nanosecs/byte mebibytes/sec cycles/byte STREAM enc | 1.97 ns/B 483.6 MiB/s 6.31 c/B STREAM dec | 1.97 ns/B 484.0 MiB/s 6.31 c/B After: CHACHA20 | nanosecs/byte mebibytes/sec cycles/byte STREAM enc | 0.742 ns/B 1284.8 MiB/s 2.38 c/B STREAM dec | 0.741 ns/B 1286.5 MiB/s 2.37 c/B Signed-off-by: Jussi Kivilinna diff --git a/cipher/Makefile.am b/cipher/Makefile.am index bc7959a..27ca7ac 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -59,7 +59,7 @@ EXTRA_libcipher_la_SOURCES = \ arcfour.c arcfour-amd64.S \ blowfish.c blowfish-amd64.S blowfish-arm.S \ cast5.c cast5-amd64.S cast5-arm.S \ -chacha20.c \ +chacha20.c chacha20-ssse3-amd64.S \ crc.c \ des.c des-amd64.S \ dsa.c \ diff --git a/cipher/chacha20-ssse3-amd64.S b/cipher/chacha20-ssse3-amd64.S new file mode 100644 index 0000000..aaa7e5b --- /dev/null +++ b/cipher/chacha20-ssse3-amd64.S @@ -0,0 +1,610 @@ +/* chacha20-ssse3-amd64.S - AMD64/SSSE3 implementation of ChaCha20 + * + * Copyright (C) 2014 Jussi Kivilinna + * + * 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, see . + */ + +/* + * Based on public domain implementation by Andrew Moon at + * https://github.com/floodyberry/chacha-opt + */ + +#ifdef __x86_64__ +#include + +#if defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) && \ + defined(HAVE_GCC_INLINE_ASM_SSSE3) && USE_CHACHA20 + +#ifdef __PIC__ +# define RIP (%rip) +#else +# define RIP +#endif + +.text + +.align 8 +.globl _gcry_chacha20_amd64_ssse3_blocks +.type _gcry_chacha20_amd64_ssse3_blocks, at function; +_gcry_chacha20_amd64_ssse3_blocks: +.Lchacha_blocks_ssse3_local: + pushq %rbx + pushq %rbp + movq %rsp, %rbp + andq $~63, %rsp + subq $512, %rsp + leaq .LC RIP, %rax + movdqa 0(%rax), %xmm6 + movdqa 16(%rax), %xmm7 + movdqu 0(%rdi), %xmm8 + movdqu 16(%rdi), %xmm9 + movdqu 32(%rdi), %xmm10 + movdqu 48(%rdi), %xmm11 + movl $20, %eax + movq $1, %r9 + movdqa %xmm8, 0(%rsp) + movdqa %xmm9, 16(%rsp) + movdqa %xmm10, 32(%rsp) + movdqa %xmm11, 48(%rsp) + movdqa %xmm6, 80(%rsp) + movdqa %xmm7, 96(%rsp) + movq %rax, 64(%rsp) + cmpq $256, %rcx + jb .Lchacha_blocks_ssse3_below256 + pshufd $0x00, %xmm8, %xmm0 + pshufd $0x55, %xmm8, %xmm1 + pshufd $0xaa, %xmm8, %xmm2 + pshufd $0xff, %xmm8, %xmm3 + movdqa %xmm0, 128(%rsp) + movdqa %xmm1, 144(%rsp) + movdqa %xmm2, 160(%rsp) + movdqa %xmm3, 176(%rsp) + pshufd $0x00, %xmm9, %xmm0 + pshufd $0x55, %xmm9, %xmm1 + pshufd $0xaa, %xmm9, %xmm2 + pshufd $0xff, %xmm9, %xmm3 + movdqa %xmm0, 192(%rsp) + movdqa %xmm1, 208(%rsp) + movdqa %xmm2, 224(%rsp) + movdqa %xmm3, 240(%rsp) + pshufd $0x00, %xmm10, %xmm0 + pshufd $0x55, %xmm10, %xmm1 + pshufd $0xaa, %xmm10, %xmm2 + pshufd $0xff, %xmm10, %xmm3 + movdqa %xmm0, 256(%rsp) + movdqa %xmm1, 272(%rsp) + movdqa %xmm2, 288(%rsp) + movdqa %xmm3, 304(%rsp) + pshufd $0xaa, %xmm11, %xmm0 + pshufd $0xff, %xmm11, %xmm1 + movdqa %xmm0, 352(%rsp) + movdqa %xmm1, 368(%rsp) + jmp .Lchacha_blocks_ssse3_atleast256 +.p2align 6,,63 + # align to 4 mod 64 + nop;nop;nop;nop; +.Lchacha_blocks_ssse3_atleast256: + movq 48(%rsp), %rax + leaq 1(%rax), %r8 + leaq 2(%rax), %r9 + leaq 3(%rax), %r10 + leaq 4(%rax), %rbx + movl %eax, 320(%rsp) + movl %r8d, 4+320(%rsp) + movl %r9d, 8+320(%rsp) + movl %r10d, 12+320(%rsp) + shrq $32, %rax + shrq $32, %r8 + shrq $32, %r9 + shrq $32, %r10 + movl %eax, 336(%rsp) + movl %r8d, 4+336(%rsp) + movl %r9d, 8+336(%rsp) + movl %r10d, 12+336(%rsp) + movq %rbx, 48(%rsp) + movq 64(%rsp), %rax + movdqa 128(%rsp), %xmm0 + movdqa 144(%rsp), %xmm1 + movdqa 160(%rsp), %xmm2 + movdqa 176(%rsp), %xmm3 + movdqa 192(%rsp), %xmm4 + movdqa 208(%rsp), %xmm5 + movdqa 224(%rsp), %xmm6 + movdqa 240(%rsp), %xmm7 + movdqa 256(%rsp), %xmm8 + movdqa 272(%rsp), %xmm9 + movdqa 288(%rsp), %xmm10 + movdqa 304(%rsp), %xmm11 + movdqa 320(%rsp), %xmm12 + movdqa 336(%rsp), %xmm13 + movdqa 352(%rsp), %xmm14 + movdqa 368(%rsp), %xmm15 +.Lchacha_blocks_ssse3_mainloop1: + paddd %xmm4, %xmm0 + paddd %xmm5, %xmm1 + pxor %xmm0, %xmm12 + pxor %xmm1, %xmm13 + paddd %xmm6, %xmm2 + paddd %xmm7, %xmm3 + pxor %xmm2, %xmm14 + pxor %xmm3, %xmm15 + pshufb 80(%rsp), %xmm12 + pshufb 80(%rsp), %xmm13 + paddd %xmm12, %xmm8 + paddd %xmm13, %xmm9 + pshufb 80(%rsp), %xmm14 + pshufb 80(%rsp), %xmm15 + paddd %xmm14, %xmm10 + paddd %xmm15, %xmm11 + movdqa %xmm12, 112(%rsp) + pxor %xmm8, %xmm4 + pxor %xmm9, %xmm5 + movdqa %xmm4, %xmm12 + pslld $ 12, %xmm4 + psrld $20, %xmm12 + pxor %xmm12, %xmm4 + movdqa %xmm5, %xmm12 + pslld $ 12, %xmm5 + psrld $20, %xmm12 + pxor %xmm12, %xmm5 + pxor %xmm10, %xmm6 + pxor %xmm11, %xmm7 + movdqa %xmm6, %xmm12 + pslld $ 12, %xmm6 + psrld $20, %xmm12 + pxor %xmm12, %xmm6 + movdqa %xmm7, %xmm12 + pslld $ 12, %xmm7 + psrld $20, %xmm12 + pxor %xmm12, %xmm7 + movdqa 112(%rsp), %xmm12 + paddd %xmm4, %xmm0 + paddd %xmm5, %xmm1 + pxor %xmm0, %xmm12 + pxor %xmm1, %xmm13 + paddd %xmm6, %xmm2 + paddd %xmm7, %xmm3 + pxor %xmm2, %xmm14 + pxor %xmm3, %xmm15 + pshufb 96(%rsp), %xmm12 + pshufb 96(%rsp), %xmm13 + paddd %xmm12, %xmm8 + paddd %xmm13, %xmm9 + pshufb 96(%rsp), %xmm14 + pshufb 96(%rsp), %xmm15 + paddd %xmm14, %xmm10 + paddd %xmm15, %xmm11 + movdqa %xmm12, 112(%rsp) + pxor %xmm8, %xmm4 + pxor %xmm9, %xmm5 + movdqa %xmm4, %xmm12 + pslld $ 7, %xmm4 + psrld $25, %xmm12 + pxor %xmm12, %xmm4 + movdqa %xmm5, %xmm12 + pslld $ 7, %xmm5 + psrld $25, %xmm12 + pxor %xmm12, %xmm5 + pxor %xmm10, %xmm6 + pxor %xmm11, %xmm7 + movdqa %xmm6, %xmm12 + pslld $ 7, %xmm6 + psrld $25, %xmm12 + pxor %xmm12, %xmm6 + movdqa %xmm7, %xmm12 + pslld $ 7, %xmm7 + psrld $25, %xmm12 + pxor %xmm12, %xmm7 + movdqa 112(%rsp), %xmm12 + paddd %xmm5, %xmm0 + paddd %xmm6, %xmm1 + pxor %xmm0, %xmm15 + pxor %xmm1, %xmm12 + paddd %xmm7, %xmm2 + paddd %xmm4, %xmm3 + pxor %xmm2, %xmm13 + pxor %xmm3, %xmm14 + pshufb 80(%rsp), %xmm15 + pshufb 80(%rsp), %xmm12 + paddd %xmm15, %xmm10 + paddd %xmm12, %xmm11 + pshufb 80(%rsp), %xmm13 + pshufb 80(%rsp), %xmm14 + paddd %xmm13, %xmm8 + paddd %xmm14, %xmm9 + movdqa %xmm15, 112(%rsp) + pxor %xmm10, %xmm5 + pxor %xmm11, %xmm6 + movdqa %xmm5, %xmm15 + pslld $ 12, %xmm5 + psrld $20, %xmm15 + pxor %xmm15, %xmm5 + movdqa %xmm6, %xmm15 + pslld $ 12, %xmm6 + psrld $20, %xmm15 + pxor %xmm15, %xmm6 + pxor %xmm8, %xmm7 + pxor %xmm9, %xmm4 + movdqa %xmm7, %xmm15 + pslld $ 12, %xmm7 + psrld $20, %xmm15 + pxor %xmm15, %xmm7 + movdqa %xmm4, %xmm15 + pslld $ 12, %xmm4 + psrld $20, %xmm15 + pxor %xmm15, %xmm4 + movdqa 112(%rsp), %xmm15 + paddd %xmm5, %xmm0 + paddd %xmm6, %xmm1 + pxor %xmm0, %xmm15 + pxor %xmm1, %xmm12 + paddd %xmm7, %xmm2 + paddd %xmm4, %xmm3 + pxor %xmm2, %xmm13 + pxor %xmm3, %xmm14 + pshufb 96(%rsp), %xmm15 + pshufb 96(%rsp), %xmm12 + paddd %xmm15, %xmm10 + paddd %xmm12, %xmm11 + pshufb 96(%rsp), %xmm13 + pshufb 96(%rsp), %xmm14 + paddd %xmm13, %xmm8 + paddd %xmm14, %xmm9 + movdqa %xmm15, 112(%rsp) + pxor %xmm10, %xmm5 + pxor %xmm11, %xmm6 + movdqa %xmm5, %xmm15 + pslld $ 7, %xmm5 + psrld $25, %xmm15 + pxor %xmm15, %xmm5 + movdqa %xmm6, %xmm15 + pslld $ 7, %xmm6 + psrld $25, %xmm15 + pxor %xmm15, %xmm6 + pxor %xmm8, %xmm7 + pxor %xmm9, %xmm4 + movdqa %xmm7, %xmm15 + pslld $ 7, %xmm7 + psrld $25, %xmm15 + pxor %xmm15, %xmm7 + movdqa %xmm4, %xmm15 + pslld $ 7, %xmm4 + psrld $25, %xmm15 + pxor %xmm15, %xmm4 + subq $2, %rax + movdqa 112(%rsp), %xmm15 + jnz .Lchacha_blocks_ssse3_mainloop1 + paddd 128(%rsp), %xmm0 + paddd 144(%rsp), %xmm1 + paddd 160(%rsp), %xmm2 + paddd 176(%rsp), %xmm3 + paddd 192(%rsp), %xmm4 + paddd 208(%rsp), %xmm5 + paddd 224(%rsp), %xmm6 + paddd 240(%rsp), %xmm7 + paddd 256(%rsp), %xmm8 + paddd 272(%rsp), %xmm9 + paddd 288(%rsp), %xmm10 + paddd 304(%rsp), %xmm11 + paddd 320(%rsp), %xmm12 + paddd 336(%rsp), %xmm13 + paddd 352(%rsp), %xmm14 + paddd 368(%rsp), %xmm15 + movdqa %xmm8, 384(%rsp) + movdqa %xmm9, 400(%rsp) + movdqa %xmm10, 416(%rsp) + movdqa %xmm11, 432(%rsp) + movdqa %xmm12, 448(%rsp) + movdqa %xmm13, 464(%rsp) + movdqa %xmm14, 480(%rsp) + movdqa %xmm15, 496(%rsp) + movdqa %xmm0, %xmm8 + movdqa %xmm2, %xmm9 + movdqa %xmm4, %xmm10 + movdqa %xmm6, %xmm11 + punpckhdq %xmm1, %xmm0 + punpckhdq %xmm3, %xmm2 + punpckhdq %xmm5, %xmm4 + punpckhdq %xmm7, %xmm6 + punpckldq %xmm1, %xmm8 + punpckldq %xmm3, %xmm9 + punpckldq %xmm5, %xmm10 + punpckldq %xmm7, %xmm11 + movdqa %xmm0, %xmm1 + movdqa %xmm4, %xmm3 + movdqa %xmm8, %xmm5 + movdqa %xmm10, %xmm7 + punpckhqdq %xmm2, %xmm0 + punpckhqdq %xmm6, %xmm4 + punpckhqdq %xmm9, %xmm8 + punpckhqdq %xmm11, %xmm10 + punpcklqdq %xmm2, %xmm1 + punpcklqdq %xmm6, %xmm3 + punpcklqdq %xmm9, %xmm5 + punpcklqdq %xmm11, %xmm7 + andq %rsi, %rsi + jz .Lchacha_blocks_ssse3_noinput1 + movdqu 0(%rsi), %xmm2 + movdqu 16(%rsi), %xmm6 + movdqu 64(%rsi), %xmm9 + movdqu 80(%rsi), %xmm11 + movdqu 128(%rsi), %xmm12 + movdqu 144(%rsi), %xmm13 + movdqu 192(%rsi), %xmm14 + movdqu 208(%rsi), %xmm15 + pxor %xmm2, %xmm5 + pxor %xmm6, %xmm7 + pxor %xmm9, %xmm8 + pxor %xmm11, %xmm10 + pxor %xmm12, %xmm1 + pxor %xmm13, %xmm3 + pxor %xmm14, %xmm0 + pxor %xmm15, %xmm4 + movdqu %xmm5, 0(%rdx) + movdqu %xmm7, 16(%rdx) + movdqu %xmm8, 64(%rdx) + movdqu %xmm10, 80(%rdx) + movdqu %xmm1, 128(%rdx) + movdqu %xmm3, 144(%rdx) + movdqu %xmm0, 192(%rdx) + movdqu %xmm4, 208(%rdx) + movdqa 384(%rsp), %xmm0 + movdqa 400(%rsp), %xmm1 + movdqa 416(%rsp), %xmm2 + movdqa 432(%rsp), %xmm3 + movdqa 448(%rsp), %xmm4 + movdqa 464(%rsp), %xmm5 + movdqa 480(%rsp), %xmm6 + movdqa 496(%rsp), %xmm7 + movdqa %xmm0, %xmm8 + movdqa %xmm2, %xmm9 + movdqa %xmm4, %xmm10 + movdqa %xmm6, %xmm11 + punpckldq %xmm1, %xmm8 + punpckldq %xmm3, %xmm9 + punpckhdq %xmm1, %xmm0 + punpckhdq %xmm3, %xmm2 + punpckldq %xmm5, %xmm10 + punpckldq %xmm7, %xmm11 + punpckhdq %xmm5, %xmm4 + punpckhdq %xmm7, %xmm6 + movdqa %xmm8, %xmm1 + movdqa %xmm0, %xmm3 + movdqa %xmm10, %xmm5 + movdqa %xmm4, %xmm7 + punpcklqdq %xmm9, %xmm1 + punpcklqdq %xmm11, %xmm5 + punpckhqdq %xmm9, %xmm8 + punpckhqdq %xmm11, %xmm10 + punpcklqdq %xmm2, %xmm3 + punpcklqdq %xmm6, %xmm7 + punpckhqdq %xmm2, %xmm0 + punpckhqdq %xmm6, %xmm4 + movdqu 32(%rsi), %xmm2 + movdqu 48(%rsi), %xmm6 + movdqu 96(%rsi), %xmm9 + movdqu 112(%rsi), %xmm11 + movdqu 160(%rsi), %xmm12 + movdqu 176(%rsi), %xmm13 + movdqu 224(%rsi), %xmm14 + movdqu 240(%rsi), %xmm15 + pxor %xmm2, %xmm1 + pxor %xmm6, %xmm5 + pxor %xmm9, %xmm8 + pxor %xmm11, %xmm10 + pxor %xmm12, %xmm3 + pxor %xmm13, %xmm7 + pxor %xmm14, %xmm0 + pxor %xmm15, %xmm4 + movdqu %xmm1, 32(%rdx) + movdqu %xmm5, 48(%rdx) + movdqu %xmm8, 96(%rdx) + movdqu %xmm10, 112(%rdx) + movdqu %xmm3, 160(%rdx) + movdqu %xmm7, 176(%rdx) + movdqu %xmm0, 224(%rdx) + movdqu %xmm4, 240(%rdx) + addq $256, %rsi + jmp .Lchacha_blocks_ssse3_mainloop_cont +.Lchacha_blocks_ssse3_noinput1: + movdqu %xmm5, 0(%rdx) + movdqu %xmm7, 16(%rdx) + movdqu %xmm8, 64(%rdx) + movdqu %xmm10, 80(%rdx) + movdqu %xmm1, 128(%rdx) + movdqu %xmm3, 144(%rdx) + movdqu %xmm0, 192(%rdx) + movdqu %xmm4, 208(%rdx) + movdqa 384(%rsp), %xmm0 + movdqa 400(%rsp), %xmm1 + movdqa 416(%rsp), %xmm2 + movdqa 432(%rsp), %xmm3 + movdqa 448(%rsp), %xmm4 + movdqa 464(%rsp), %xmm5 + movdqa 480(%rsp), %xmm6 + movdqa 496(%rsp), %xmm7 + movdqa %xmm0, %xmm8 + movdqa %xmm2, %xmm9 + movdqa %xmm4, %xmm10 + movdqa %xmm6, %xmm11 + punpckldq %xmm1, %xmm8 + punpckldq %xmm3, %xmm9 + punpckhdq %xmm1, %xmm0 + punpckhdq %xmm3, %xmm2 + punpckldq %xmm5, %xmm10 + punpckldq %xmm7, %xmm11 + punpckhdq %xmm5, %xmm4 + punpckhdq %xmm7, %xmm6 + movdqa %xmm8, %xmm1 + movdqa %xmm0, %xmm3 + movdqa %xmm10, %xmm5 + movdqa %xmm4, %xmm7 + punpcklqdq %xmm9, %xmm1 + punpcklqdq %xmm11, %xmm5 + punpckhqdq %xmm9, %xmm8 + punpckhqdq %xmm11, %xmm10 + punpcklqdq %xmm2, %xmm3 + punpcklqdq %xmm6, %xmm7 + punpckhqdq %xmm2, %xmm0 + punpckhqdq %xmm6, %xmm4 + movdqu %xmm1, 32(%rdx) + movdqu %xmm5, 48(%rdx) + movdqu %xmm8, 96(%rdx) + movdqu %xmm10, 112(%rdx) + movdqu %xmm3, 160(%rdx) + movdqu %xmm7, 176(%rdx) + movdqu %xmm0, 224(%rdx) + movdqu %xmm4, 240(%rdx) +.Lchacha_blocks_ssse3_mainloop_cont: + addq $256, %rdx + subq $256, %rcx + cmp $256, %rcx + jae .Lchacha_blocks_ssse3_atleast256 + movdqa 80(%rsp), %xmm6 + movdqa 96(%rsp), %xmm7 + movdqa 0(%rsp), %xmm8 + movdqa 16(%rsp), %xmm9 + movdqa 32(%rsp), %xmm10 + movdqa 48(%rsp), %xmm11 + movq $1, %r9 +.Lchacha_blocks_ssse3_below256: + movq %r9, %xmm5 + andq %rcx, %rcx + jz .Lchacha_blocks_ssse3_done + cmpq $64, %rcx + jae .Lchacha_blocks_ssse3_above63 + movq %rdx, %r9 + andq %rsi, %rsi + jz .Lchacha_blocks_ssse3_noinput2 + movq %rcx, %r10 + movq %rsp, %rdx + addq %r10, %rsi + addq %r10, %rdx + negq %r10 +.Lchacha_blocks_ssse3_copyinput: + movb (%rsi, %r10), %al + movb %al, (%rdx, %r10) + incq %r10 + jnz .Lchacha_blocks_ssse3_copyinput + movq %rsp, %rsi +.Lchacha_blocks_ssse3_noinput2: + movq %rsp, %rdx +.Lchacha_blocks_ssse3_above63: + movdqa %xmm8, %xmm0 + movdqa %xmm9, %xmm1 + movdqa %xmm10, %xmm2 + movdqa %xmm11, %xmm3 + movq 64(%rsp), %rax +.Lchacha_blocks_ssse3_mainloop2: + paddd %xmm1, %xmm0 + pxor %xmm0, %xmm3 + pshufb %xmm6, %xmm3 + paddd %xmm3, %xmm2 + pxor %xmm2, %xmm1 + movdqa %xmm1, %xmm4 + pslld $12, %xmm4 + psrld $20, %xmm1 + pxor %xmm4, %xmm1 + paddd %xmm1, %xmm0 + pxor %xmm0, %xmm3 + pshufb %xmm7, %xmm3 + pshufd $0x93, %xmm0, %xmm0 + paddd %xmm3, %xmm2 + pshufd $0x4e, %xmm3, %xmm3 + pxor %xmm2, %xmm1 + pshufd $0x39, %xmm2, %xmm2 + movdqa %xmm1, %xmm4 + pslld $7, %xmm4 + psrld $25, %xmm1 + pxor %xmm4, %xmm1 + paddd %xmm1, %xmm0 + pxor %xmm0, %xmm3 + pshufb %xmm6, %xmm3 + paddd %xmm3, %xmm2 + pxor %xmm2, %xmm1 + movdqa %xmm1, %xmm4 + pslld $12, %xmm4 + psrld $20, %xmm1 + pxor %xmm4, %xmm1 + paddd %xmm1, %xmm0 + pxor %xmm0, %xmm3 + pshufb %xmm7, %xmm3 + pshufd $0x39, %xmm0, %xmm0 + paddd %xmm3, %xmm2 + pshufd $0x4e, %xmm3, %xmm3 + pxor %xmm2, %xmm1 + pshufd $0x93, %xmm2, %xmm2 + movdqa %xmm1, %xmm4 + pslld $7, %xmm4 + psrld $25, %xmm1 + pxor %xmm4, %xmm1 + subq $2, %rax + jnz .Lchacha_blocks_ssse3_mainloop2 + paddd %xmm8, %xmm0 + paddd %xmm9, %xmm1 + paddd %xmm10, %xmm2 + paddd %xmm11, %xmm3 + andq %rsi, %rsi + jz .Lchacha_blocks_ssse3_noinput3 + movdqu 0(%rsi), %xmm12 + movdqu 16(%rsi), %xmm13 + movdqu 32(%rsi), %xmm14 + movdqu 48(%rsi), %xmm15 + pxor %xmm12, %xmm0 + pxor %xmm13, %xmm1 + pxor %xmm14, %xmm2 + pxor %xmm15, %xmm3 + addq $64, %rsi +.Lchacha_blocks_ssse3_noinput3: + movdqu %xmm0, 0(%rdx) + movdqu %xmm1, 16(%rdx) + movdqu %xmm2, 32(%rdx) + movdqu %xmm3, 48(%rdx) + paddq %xmm5, %xmm11 + cmpq $64, %rcx + jbe .Lchacha_blocks_ssse3_mainloop2_finishup + addq $64, %rdx + subq $64, %rcx + jmp .Lchacha_blocks_ssse3_below256 +.Lchacha_blocks_ssse3_mainloop2_finishup: + cmpq $64, %rcx + je .Lchacha_blocks_ssse3_done + addq %rcx, %r9 + addq %rcx, %rdx + negq %rcx +.Lchacha_blocks_ssse3_copyoutput: + movb (%rdx, %rcx), %al + movb %al, (%r9, %rcx) + incq %rcx + jnz .Lchacha_blocks_ssse3_copyoutput +.Lchacha_blocks_ssse3_done: + movdqu %xmm11, 48(%rdi) + movq %rbp, %rsp + popq %rbp + popq %rbx + movl $(63 + 512 + 16), %eax + ret +.size _gcry_chacha20_amd64_ssse3_blocks,.-_gcry_chacha20_amd64_ssse3_blocks; + +.data +.align 16; +.LC: +.byte 2,3,0,1,6,7,4,5,10,11,8,9,14,15,12,13 /* pshufb rotate by 16 */ +.byte 3,0,1,2,7,4,5,6,11,8,9,10,15,12,13,14 /* pshufb rotate by 8 */ + +#endif /*defined(USE_CHACHA20)*/ +#endif /*__x86_64*/ diff --git a/cipher/chacha20.c b/cipher/chacha20.c index ff0366d..de8982b 100644 --- a/cipher/chacha20.c +++ b/cipher/chacha20.c @@ -47,6 +47,13 @@ #define CHACHA20_MAX_IV_SIZE 12 /* Bytes. */ #define CHACHA20_INPUT_LENGTH (CHACHA20_BLOCK_SIZE / 4) +/* USE_SSSE3 indicates whether to compile with Intel SSSE3 code. */ +#undef USE_SSSE3 +#if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) && \ + defined(HAVE_GCC_INLINE_ASM_SSSE3) +# define USE_SSSE3 1 +#endif + struct CHACHA20_context_s; @@ -63,6 +70,14 @@ typedef struct CHACHA20_context_s } CHACHA20_context_t; +#ifdef USE_SSSE3 + +unsigned int _gcry_chacha20_amd64_ssse3_blocks(u32 *state, const byte *in, + byte *out, size_t bytes); + +#endif /* USE_SSSE3 */ + + static void chacha20_setiv (void *context, const byte * iv, size_t ivlen); static const char *selftest (void); @@ -279,6 +294,7 @@ chacha20_do_setkey (CHACHA20_context_t * ctx, { static int initialized; static const char *selftest_failed; + unsigned int features = _gcry_get_hw_features (); if (!initialized) { @@ -294,6 +310,12 @@ chacha20_do_setkey (CHACHA20_context_t * ctx, return GPG_ERR_INV_KEYLEN; ctx->blocks = chacha20_blocks; +#ifdef USE_SSSE3 + if (features & HWF_INTEL_SSSE3) + ctx->blocks = _gcry_chacha20_amd64_ssse3_blocks; +#endif + + (void)features; chacha20_keysetup (ctx, key, keylen); diff --git a/configure.ac b/configure.ac index 7573952..0342067 100644 --- a/configure.ac +++ b/configure.ac @@ -1811,6 +1811,13 @@ LIST_MEMBER(chacha20, $enabled_ciphers) if test "$found" = "1" ; then GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20.lo" AC_DEFINE(USE_CHACHA20, 1, [Defined if this module should be included]) + + case "${host}" in + x86_64-*-*) + # Build with the assembly implementation + GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-ssse3-amd64.lo" + ;; + esac fi LIST_MEMBER(dsa, $enabled_pubkey_ciphers) commit 23f33d57c9b6f2295a8ddfc9a8eee5a2c30cf406 Author: Jussi Kivilinna Date: Sun May 11 12:00:19 2014 +0300 Add ChaCha20 stream cipher * cipher/Makefile.am: Add 'chacha20.c'. * cipher/chacha20.c: New. * cipher/cipher.c (cipher_list): Add ChaCha20. * configure.ac: Add ChaCha20. * doc/gcrypt.texi: Add ChaCha20. * src/cipher.h (_gcry_cipher_spec_chacha20): New. * src/gcrypt.h.in (GCRY_CIPHER_CHACHA20): Add new algo. * tests/basic.c (MAX_DATA_LEN): Increase to 128 from 100. (check_stream_cipher): Add ChaCha20 test-vectors. (check_ciphers): Add ChaCha20. -- Patch adds Bernstein's ChaCha20 cipher to libgcrypt. Implementation is based on public domain implementations. Signed-off-by: Jussi Kivilinna diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 3c20d3c..bc7959a 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -59,6 +59,7 @@ EXTRA_libcipher_la_SOURCES = \ arcfour.c arcfour-amd64.S \ blowfish.c blowfish-amd64.S blowfish-arm.S \ cast5.c cast5-amd64.S cast5-arm.S \ +chacha20.c \ crc.c \ des.c des-amd64.S \ dsa.c \ diff --git a/cipher/chacha20.c b/cipher/chacha20.c new file mode 100644 index 0000000..ff0366d --- /dev/null +++ b/cipher/chacha20.c @@ -0,0 +1,504 @@ +/* chacha20.c - Bernstein's ChaCha20 cipher + * Copyright (C) 2014 Jussi Kivilinna + * + * 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, see . + * + * For a description of the algorithm, see: + * http://cr.yp.to/chacha.html + */ + +/* The code is based on salsa20.c and public-domain ChaCha implementations: + * chacha-ref.c version 20080118 + * D. J. Bernstein + * Public domain. + * and + * Andrew Moon + * https://github.com/floodyberry/chacha-opt + */ + + +#include +#include +#include +#include +#include "types.h" +#include "g10lib.h" +#include "cipher.h" +#include "bufhelp.h" + + +#define CHACHA20_MIN_KEY_SIZE 16 /* Bytes. */ +#define CHACHA20_MAX_KEY_SIZE 32 /* Bytes. */ +#define CHACHA20_BLOCK_SIZE 64 /* Bytes. */ +#define CHACHA20_MIN_IV_SIZE 8 /* Bytes. */ +#define CHACHA20_MAX_IV_SIZE 12 /* Bytes. */ +#define CHACHA20_INPUT_LENGTH (CHACHA20_BLOCK_SIZE / 4) + + +struct CHACHA20_context_s; + + +typedef unsigned int (* chacha20_blocks_t)(u32 *state, const byte *src, + byte *dst, size_t bytes); + +typedef struct CHACHA20_context_s +{ + u32 input[CHACHA20_INPUT_LENGTH]; + u32 pad[CHACHA20_INPUT_LENGTH]; + chacha20_blocks_t blocks; + unsigned int unused; /* bytes in the pad. */ +} CHACHA20_context_t; + + +static void chacha20_setiv (void *context, const byte * iv, size_t ivlen); +static const char *selftest (void); + + + +#define QROUND(a,b,c,d) \ + do { \ + a += b; d = rol(d ^ a, 16); \ + c += d; b = rol(b ^ c, 12); \ + a += b; d = rol(d ^ a, 8); \ + c += d; b = rol(b ^ c, 7); \ + } while (0) + +#define QOUT(ai, bi, ci, di) \ + DO_OUT(ai); DO_OUT(bi); DO_OUT(ci); DO_OUT(di) + +static unsigned int +chacha20_blocks (u32 *state, const byte *src, byte *dst, size_t bytes) +{ + u32 pad[CHACHA20_INPUT_LENGTH]; + u32 inp[CHACHA20_INPUT_LENGTH]; + unsigned int i; + + /* Note: 'bytes' must be multiple of 64 and not zero. */ + + inp[0] = state[0]; + inp[1] = state[1]; + inp[2] = state[2]; + inp[3] = state[3]; + inp[4] = state[4]; + inp[5] = state[5]; + inp[6] = state[6]; + inp[7] = state[7]; + inp[8] = state[8]; + inp[9] = state[9]; + inp[10] = state[10]; + inp[11] = state[11]; + inp[12] = state[12]; + inp[13] = state[13]; + inp[14] = state[14]; + inp[15] = state[15]; + + do + { + /* First round. */ + pad[0] = inp[0]; + pad[4] = inp[4]; + pad[8] = inp[8]; + pad[12] = inp[12]; + QROUND (pad[0], pad[4], pad[8], pad[12]); + pad[1] = inp[1]; + pad[5] = inp[5]; + pad[9] = inp[9]; + pad[13] = inp[13]; + QROUND (pad[1], pad[5], pad[9], pad[13]); + pad[2] = inp[2]; + pad[6] = inp[6]; + pad[10] = inp[10]; + pad[14] = inp[14]; + QROUND (pad[2], pad[6], pad[10], pad[14]); + pad[3] = inp[3]; + pad[7] = inp[7]; + pad[11] = inp[11]; + pad[15] = inp[15]; + QROUND (pad[3], pad[7], pad[11], pad[15]); + + QROUND (pad[0], pad[5], pad[10], pad[15]); + QROUND (pad[1], pad[6], pad[11], pad[12]); + QROUND (pad[2], pad[7], pad[8], pad[13]); + QROUND (pad[3], pad[4], pad[9], pad[14]); + + for (i = 2; i < 20 - 2; i += 2) + { + QROUND (pad[0], pad[4], pad[8], pad[12]); + QROUND (pad[1], pad[5], pad[9], pad[13]); + QROUND (pad[2], pad[6], pad[10], pad[14]); + QROUND (pad[3], pad[7], pad[11], pad[15]); + + QROUND (pad[0], pad[5], pad[10], pad[15]); + QROUND (pad[1], pad[6], pad[11], pad[12]); + QROUND (pad[2], pad[7], pad[8], pad[13]); + QROUND (pad[3], pad[4], pad[9], pad[14]); + } + + QROUND (pad[0], pad[4], pad[8], pad[12]); + QROUND (pad[1], pad[5], pad[9], pad[13]); + QROUND (pad[2], pad[6], pad[10], pad[14]); + QROUND (pad[3], pad[7], pad[11], pad[15]); + + if (src) + { +#define DO_OUT(idx) buf_put_le32(dst + (idx) * 4, \ + (pad[idx] + inp[idx]) ^ \ + buf_get_le32(src + (idx) * 4)) + /* Last round. */ + QROUND (pad[0], pad[5], pad[10], pad[15]); + QOUT(0, 5, 10, 15); + QROUND (pad[1], pad[6], pad[11], pad[12]); + QOUT(1, 6, 11, 12); + QROUND (pad[2], pad[7], pad[8], pad[13]); + QOUT(2, 7, 8, 13); + QROUND (pad[3], pad[4], pad[9], pad[14]); + QOUT(3, 4, 9, 14); +#undef DO_OUT + } + else + { +#define DO_OUT(idx) buf_put_le32(dst + (idx) * 4, pad[idx] + inp[idx]) + /* Last round. */ + QROUND (pad[0], pad[5], pad[10], pad[15]); + QOUT(0, 5, 10, 15); + QROUND (pad[1], pad[6], pad[11], pad[12]); + QOUT(1, 6, 11, 12); + QROUND (pad[2], pad[7], pad[8], pad[13]); + QOUT(2, 7, 8, 13); + QROUND (pad[3], pad[4], pad[9], pad[14]); + QOUT(3, 4, 9, 14); +#undef DO_OUT + } + + /* Update counter. */ + inp[13] += (!++inp[12]); + + bytes -= CHACHA20_BLOCK_SIZE; + dst += CHACHA20_BLOCK_SIZE; + src += (src) ? CHACHA20_BLOCK_SIZE : 0; + } + while (bytes >= CHACHA20_BLOCK_SIZE); + + state[12] = inp[12]; + state[13] = inp[13]; + + /* burn_stack */ + return (2 * CHACHA20_INPUT_LENGTH * sizeof(u32) + 6 * sizeof(void *)); +} + +#undef QROUND +#undef QOUT + + +static unsigned int +chacha20_core(u32 *dst, struct CHACHA20_context_s *ctx) +{ + return ctx->blocks(ctx->input, NULL, (byte *)dst, CHACHA20_BLOCK_SIZE); +} + + +static void +chacha20_keysetup (CHACHA20_context_t * ctx, const byte * key, + unsigned int keylen) +{ + /* These constants are the little endian encoding of the string + "expand 32-byte k". For the 128 bit variant, the "32" in that + string will be fixed up to "16". */ + ctx->input[0] = 0x61707865; /* "apxe" */ + ctx->input[1] = 0x3320646e; /* "3 dn" */ + ctx->input[2] = 0x79622d32; /* "yb-2" */ + ctx->input[3] = 0x6b206574; /* "k et" */ + + ctx->input[4] = buf_get_le32 (key + 0); + ctx->input[5] = buf_get_le32 (key + 4); + ctx->input[6] = buf_get_le32 (key + 8); + ctx->input[7] = buf_get_le32 (key + 12); + + if (keylen == CHACHA20_MAX_KEY_SIZE) /* 256 bits */ + { + ctx->input[8] = buf_get_le32 (key + 16); + ctx->input[9] = buf_get_le32 (key + 20); + ctx->input[10] = buf_get_le32 (key + 24); + ctx->input[11] = buf_get_le32 (key + 28); + } + else /* 128 bits */ + { + ctx->input[8] = ctx->input[4]; + ctx->input[9] = ctx->input[5]; + ctx->input[10] = ctx->input[6]; + ctx->input[11] = ctx->input[7]; + + ctx->input[1] -= 0x02000000; /* Change to "1 dn". */ + ctx->input[2] += 0x00000004; /* Change to "yb-6". */ + } +} + + +static void +chacha20_ivsetup (CHACHA20_context_t * ctx, const byte * iv, size_t ivlen) +{ + ctx->input[12] = 0; + + if (ivlen == CHACHA20_MAX_IV_SIZE) + { + ctx->input[13] = buf_get_le32 (iv + 0); + ctx->input[14] = buf_get_le32 (iv + 4); + ctx->input[15] = buf_get_le32 (iv + 8); + } + else if (ivlen == CHACHA20_MIN_IV_SIZE) + { + ctx->input[13] = 0; + ctx->input[14] = buf_get_le32 (iv + 0); + ctx->input[15] = buf_get_le32 (iv + 4); + } + else + { + ctx->input[13] = 0; + ctx->input[14] = 0; + ctx->input[15] = 0; + } +} + + +static gcry_err_code_t +chacha20_do_setkey (CHACHA20_context_t * ctx, + const byte * key, unsigned int keylen) +{ + static int initialized; + static const char *selftest_failed; + + if (!initialized) + { + initialized = 1; + selftest_failed = selftest (); + if (selftest_failed) + log_error ("CHACHA20 selftest failed (%s)\n", selftest_failed); + } + if (selftest_failed) + return GPG_ERR_SELFTEST_FAILED; + + if (keylen != CHACHA20_MAX_KEY_SIZE && keylen != CHACHA20_MIN_KEY_SIZE) + return GPG_ERR_INV_KEYLEN; + + ctx->blocks = chacha20_blocks; + + chacha20_keysetup (ctx, key, keylen); + + /* We default to a zero nonce. */ + chacha20_setiv (ctx, NULL, 0); + + return 0; +} + + +static gcry_err_code_t +chacha20_setkey (void *context, const byte * key, unsigned int keylen) +{ + CHACHA20_context_t *ctx = (CHACHA20_context_t *) context; + gcry_err_code_t rc = chacha20_do_setkey (ctx, key, keylen); + _gcry_burn_stack (4 + sizeof (void *) + 4 * sizeof (void *)); + return rc; +} + + +static void +chacha20_setiv (void *context, const byte * iv, size_t ivlen) +{ + CHACHA20_context_t *ctx = (CHACHA20_context_t *) context; + + /* draft-nir-cfrg-chacha20-poly1305-02 defines 96-bit and 64-bit nonce. */ + if (iv && ivlen != CHACHA20_MAX_IV_SIZE && ivlen != CHACHA20_MIN_IV_SIZE) + log_info ("WARNING: chacha20_setiv: bad ivlen=%u\n", (u32) ivlen); + + if (iv && (ivlen == CHACHA20_MAX_IV_SIZE || ivlen == CHACHA20_MIN_IV_SIZE)) + chacha20_ivsetup (ctx, iv, ivlen); + else + chacha20_ivsetup (ctx, NULL, 0); + + /* Reset the unused pad bytes counter. */ + ctx->unused = 0; +} + + + +/* Note: This function requires LENGTH > 0. */ +static void +chacha20_do_encrypt_stream (CHACHA20_context_t * ctx, + byte * outbuf, const byte * inbuf, size_t length) +{ + unsigned int nburn, burn = 0; + + if (ctx->unused) + { + unsigned char *p = (void *) ctx->pad; + size_t n; + + gcry_assert (ctx->unused < CHACHA20_BLOCK_SIZE); + + n = ctx->unused; + if (n > length) + n = length; + buf_xor (outbuf, inbuf, p + CHACHA20_BLOCK_SIZE - ctx->unused, n); + length -= n; + outbuf += n; + inbuf += n; + ctx->unused -= n; + if (!length) + return; + gcry_assert (!ctx->unused); + } + + if (length >= CHACHA20_BLOCK_SIZE) + { + size_t nblocks = length / CHACHA20_BLOCK_SIZE; + size_t bytes = nblocks * CHACHA20_BLOCK_SIZE; + burn = ctx->blocks(ctx->input, inbuf, outbuf, bytes); + length -= bytes; + outbuf += bytes; + inbuf += bytes; + } + + if (length > 0) + { + nburn = chacha20_core (ctx->pad, ctx); + burn = nburn > burn ? nburn : burn; + + buf_xor (outbuf, inbuf, ctx->pad, length); + ctx->unused = CHACHA20_BLOCK_SIZE - length; + } + + _gcry_burn_stack (burn); +} + + +static void +chacha20_encrypt_stream (void *context, byte * outbuf, const byte * inbuf, + size_t length) +{ + CHACHA20_context_t *ctx = (CHACHA20_context_t *) context; + + if (length) + chacha20_do_encrypt_stream (ctx, outbuf, inbuf, length); +} + + +static const char * +selftest (void) +{ + CHACHA20_context_t ctx; + byte scratch[127 + 1]; + byte buf[256 + 64 + 4]; + int i; + + /* From draft-strombergson-chacha-test-vectors */ + static byte key_1[] = { + 0xc4, 0x6e, 0xc1, 0xb1, 0x8c, 0xe8, 0xa8, 0x78, + 0x72, 0x5a, 0x37, 0xe7, 0x80, 0xdf, 0xb7, 0x35, + 0x1f, 0x68, 0xed, 0x2e, 0x19, 0x4c, 0x79, 0xfb, + 0xc6, 0xae, 0xbe, 0xe1, 0xa6, 0x67, 0x97, 0x5d + }; + static const byte nonce_1[] = + { 0x1a, 0xda, 0x31, 0xd5, 0xcf, 0x68, 0x82, 0x21 }; + static const byte plaintext_1[127] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + static const byte ciphertext_1[127] = { + 0xf6, 0x3a, 0x89, 0xb7, 0x5c, 0x22, 0x71, 0xf9, + 0x36, 0x88, 0x16, 0x54, 0x2b, 0xa5, 0x2f, 0x06, + 0xed, 0x49, 0x24, 0x17, 0x92, 0x30, 0x2b, 0x00, + 0xb5, 0xe8, 0xf8, 0x0a, 0xe9, 0xa4, 0x73, 0xaf, + 0xc2, 0x5b, 0x21, 0x8f, 0x51, 0x9a, 0xf0, 0xfd, + 0xd4, 0x06, 0x36, 0x2e, 0x8d, 0x69, 0xde, 0x7f, + 0x54, 0xc6, 0x04, 0xa6, 0xe0, 0x0f, 0x35, 0x3f, + 0x11, 0x0f, 0x77, 0x1b, 0xdc, 0xa8, 0xab, 0x92, + 0xe5, 0xfb, 0xc3, 0x4e, 0x60, 0xa1, 0xd9, 0xa9, + 0xdb, 0x17, 0x34, 0x5b, 0x0a, 0x40, 0x27, 0x36, + 0x85, 0x3b, 0xf9, 0x10, 0xb0, 0x60, 0xbd, 0xf1, + 0xf8, 0x97, 0xb6, 0x29, 0x0f, 0x01, 0xd1, 0x38, + 0xae, 0x2c, 0x4c, 0x90, 0x22, 0x5b, 0xa9, 0xea, + 0x14, 0xd5, 0x18, 0xf5, 0x59, 0x29, 0xde, 0xa0, + 0x98, 0xca, 0x7a, 0x6c, 0xcf, 0xe6, 0x12, 0x27, + 0x05, 0x3c, 0x84, 0xe4, 0x9a, 0x4a, 0x33 + }; + + chacha20_setkey (&ctx, key_1, sizeof key_1); + chacha20_setiv (&ctx, nonce_1, sizeof nonce_1); + scratch[sizeof (scratch) - 1] = 0; + chacha20_encrypt_stream (&ctx, scratch, plaintext_1, sizeof plaintext_1); + if (memcmp (scratch, ciphertext_1, sizeof ciphertext_1)) + return "ChaCha20 encryption test 1 failed."; + if (scratch[sizeof (scratch) - 1]) + return "ChaCha20 wrote too much."; + chacha20_setkey (&ctx, key_1, sizeof (key_1)); + chacha20_setiv (&ctx, nonce_1, sizeof nonce_1); + chacha20_encrypt_stream (&ctx, scratch, scratch, sizeof plaintext_1); + if (memcmp (scratch, plaintext_1, sizeof plaintext_1)) + return "ChaCha20 decryption test 1 failed."; + + for (i = 0; i < sizeof buf; i++) + buf[i] = i; + chacha20_setkey (&ctx, key_1, sizeof key_1); + chacha20_setiv (&ctx, nonce_1, sizeof nonce_1); + /*encrypt */ + chacha20_encrypt_stream (&ctx, buf, buf, sizeof buf); + /*decrypt */ + chacha20_setkey (&ctx, key_1, sizeof key_1); + chacha20_setiv (&ctx, nonce_1, sizeof nonce_1); + chacha20_encrypt_stream (&ctx, buf, buf, 1); + chacha20_encrypt_stream (&ctx, buf + 1, buf + 1, (sizeof buf) - 1 - 1); + chacha20_encrypt_stream (&ctx, buf + (sizeof buf) - 1, + buf + (sizeof buf) - 1, 1); + for (i = 0; i < sizeof buf; i++) + if (buf[i] != (byte) i) + return "ChaCha20 encryption test 2 failed."; + + return NULL; +} + + +gcry_cipher_spec_t _gcry_cipher_spec_chacha20 = { + GCRY_CIPHER_CHACHA20, + {0, 0}, /* flags */ + "CHACHA20", /* name */ + NULL, /* aliases */ + NULL, /* oids */ + 1, /* blocksize in bytes. */ + CHACHA20_MAX_KEY_SIZE * 8, /* standard key length in bits. */ + sizeof (CHACHA20_context_t), + chacha20_setkey, + NULL, + NULL, + chacha20_encrypt_stream, + chacha20_encrypt_stream, + NULL, + NULL, + chacha20_setiv +}; diff --git a/cipher/cipher.c b/cipher/cipher.c index 6552ed3..4751302 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -83,6 +83,9 @@ static gcry_cipher_spec_t *cipher_list[] = #if USE_GOST28147 &_gcry_cipher_spec_gost28147, #endif +#if USE_CHACHA20 + &_gcry_cipher_spec_chacha20, +#endif NULL }; diff --git a/configure.ac b/configure.ac index 6539a96..7573952 100644 --- a/configure.ac +++ b/configure.ac @@ -187,7 +187,7 @@ LIBGCRYPT_CONFIG_HOST="$host" # Definitions for symmetric ciphers. available_ciphers="arcfour blowfish cast5 des aes twofish serpent rfc2268 seed" -available_ciphers="$available_ciphers camellia idea salsa20 gost28147" +available_ciphers="$available_ciphers camellia idea salsa20 gost28147 chacha20" enabled_ciphers="" # Definitions for public-key ciphers. @@ -1807,6 +1807,12 @@ if test "$found" = "1" ; then AC_DEFINE(USE_GOST28147, 1, [Defined if this module should be included]) fi +LIST_MEMBER(chacha20, $enabled_ciphers) +if test "$found" = "1" ; then + GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20.lo" + AC_DEFINE(USE_CHACHA20, 1, [Defined if this module should be included]) +fi + LIST_MEMBER(dsa, $enabled_pubkey_ciphers) if test "$found" = "1" ; then GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS dsa.lo" diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index c5c3b45..d202b8b 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -1564,6 +1564,10 @@ This is the Salsa20/12 - reduced round version of Salsa20 stream cipher. The GOST 28147-89 cipher, defined in the respective GOST standard. Translation of this GOST into English is provided in the RFC-5830. + at item GCRY_CIPHER_CHACHA20 + at cindex ChaCha20 +This is the ChaCha20 stream cipher. + @end table @node Available cipher modes @@ -1720,9 +1724,9 @@ vector is passed as the buffer @var{K} of length @var{l} bytes and copied to internal data structures. The function checks that the IV matches the requirement of the selected algorithm and mode. -This function is also used with the Salsa20 stream cipher to set or -update the required nonce. In this case it needs to be called after -setting the key. +This function is also used with Salsa20 and ChaCha20 stream ciphers +to set or update the required nonce. In this case it needs to be +called after setting the key. This function is also used with the AEAD cipher modes to set or update the required nonce. diff --git a/src/cipher.h b/src/cipher.h index 5d1b5f6..ed57d3c 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -251,6 +251,7 @@ extern gcry_cipher_spec_t _gcry_cipher_spec_idea; extern gcry_cipher_spec_t _gcry_cipher_spec_salsa20; extern gcry_cipher_spec_t _gcry_cipher_spec_salsa20r12; extern gcry_cipher_spec_t _gcry_cipher_spec_gost28147; +extern gcry_cipher_spec_t _gcry_cipher_spec_chacha20; /* Declarations for the digest specifications. */ extern gcry_md_spec_t _gcry_digest_spec_crc32; diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index c84a3f7..d4e9bb2 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -880,7 +880,8 @@ enum gcry_cipher_algos GCRY_CIPHER_CAMELLIA256 = 312, GCRY_CIPHER_SALSA20 = 313, GCRY_CIPHER_SALSA20R12 = 314, - GCRY_CIPHER_GOST28147 = 315 + GCRY_CIPHER_GOST28147 = 315, + GCRY_CIPHER_CHACHA20 = 316 }; /* The Rijndael algorithm is basically AES, so provide some macros. */ diff --git a/tests/basic.c b/tests/basic.c index 5c6c51c..406d82d 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -195,7 +195,7 @@ show_mac_not_available (int algo) -#define MAX_DATA_LEN 100 +#define MAX_DATA_LEN 128 void progress_handler (void *cb_data, const char *what, int printchar, @@ -2583,8 +2583,331 @@ check_stream_cipher (void) "\x44\xC9\x70\x0A\x0F\x21\x38\xE8\xC1\xA2\x86\xFB\x8C\x1F\xBF\xA0" } } - } + }, #endif /*USE_SALSA20*/ +#ifdef USE_CHACHA20 + /* From draft-strombergson-chacha-test-vectors-01 */ + { + "ChaCha20 128 bit, TC1", + GCRY_CIPHER_CHACHA20, 16, 8, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00", + { + { 8, + "\x00\x00\x00\x00\x00\x00\x00\x00", + "\x89\x67\x09\x52\x60\x83\x64\xfd" + }, + { 112, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x89\x67\x09\x52\x60\x83\x64\xfd\x00\xb2\xf9\x09\x36\xf0\x31\xc8" + "\xe7\x56\xe1\x5d\xba\x04\xb8\x49\x3d\x00\x42\x92\x59\xb2\x0f\x46" + "\xcc\x04\xf1\x11\x24\x6b\x6c\x2c\xe0\x66\xbe\x3b\xfb\x32\xd9\xaa" + "\x0f\xdd\xfb\xc1\x21\x23\xd4\xb9\xe4\x4f\x34\xdc\xa0\x5a\x10\x3f" + "\x6c\xd1\x35\xc2\x87\x8c\x83\x2b\x58\x96\xb1\x34\xf6\x14\x2a\x9d" + "\x4d\x8d\x0d\x8f\x10\x26\xd2\x0a\x0a\x81\x51\x2c\xbc\xe6\xe9\x75" + "\x8a\x71\x43\xd0\x21\x97\x80\x22\xa3\x84\x14\x1a\x80\xce\xa3\x06" + }, + { 128, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x89\x67\x09\x52\x60\x83\x64\xfd\x00\xb2\xf9\x09\x36\xf0\x31\xc8" + "\xe7\x56\xe1\x5d\xba\x04\xb8\x49\x3d\x00\x42\x92\x59\xb2\x0f\x46" + "\xcc\x04\xf1\x11\x24\x6b\x6c\x2c\xe0\x66\xbe\x3b\xfb\x32\xd9\xaa" + "\x0f\xdd\xfb\xc1\x21\x23\xd4\xb9\xe4\x4f\x34\xdc\xa0\x5a\x10\x3f" + "\x6c\xd1\x35\xc2\x87\x8c\x83\x2b\x58\x96\xb1\x34\xf6\x14\x2a\x9d" + "\x4d\x8d\x0d\x8f\x10\x26\xd2\x0a\x0a\x81\x51\x2c\xbc\xe6\xe9\x75" + "\x8a\x71\x43\xd0\x21\x97\x80\x22\xa3\x84\x14\x1a\x80\xce\xa3\x06" + "\x2f\x41\xf6\x7a\x75\x2e\x66\xad\x34\x11\x98\x4c\x78\x7e\x30\xad" + } + } + }, + { + "ChaCha20 256 bit, TC1", + GCRY_CIPHER_CHACHA20, 32, 8, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00", + { + { 8, + "\x00\x00\x00\x00\x00\x00\x00\x00", + "\x76\xb8\xe0\xad\xa0\xf1\x3d\x90" + }, + { 112, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x76\xb8\xe0\xad\xa0\xf1\x3d\x90\x40\x5d\x6a\xe5\x53\x86\xbd\x28" + "\xbd\xd2\x19\xb8\xa0\x8d\xed\x1a\xa8\x36\xef\xcc\x8b\x77\x0d\xc7" + "\xda\x41\x59\x7c\x51\x57\x48\x8d\x77\x24\xe0\x3f\xb8\xd8\x4a\x37" + "\x6a\x43\xb8\xf4\x15\x18\xa1\x1c\xc3\x87\xb6\x69\xb2\xee\x65\x86" + "\x9f\x07\xe7\xbe\x55\x51\x38\x7a\x98\xba\x97\x7c\x73\x2d\x08\x0d" + "\xcb\x0f\x29\xa0\x48\xe3\x65\x69\x12\xc6\x53\x3e\x32\xee\x7a\xed" + "\x29\xb7\x21\x76\x9c\xe6\x4e\x43\xd5\x71\x33\xb0\x74\xd8\x39\xd5" + }, + { 128, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x76\xb8\xe0\xad\xa0\xf1\x3d\x90\x40\x5d\x6a\xe5\x53\x86\xbd\x28" + "\xbd\xd2\x19\xb8\xa0\x8d\xed\x1a\xa8\x36\xef\xcc\x8b\x77\x0d\xc7" + "\xda\x41\x59\x7c\x51\x57\x48\x8d\x77\x24\xe0\x3f\xb8\xd8\x4a\x37" + "\x6a\x43\xb8\xf4\x15\x18\xa1\x1c\xc3\x87\xb6\x69\xb2\xee\x65\x86" + "\x9f\x07\xe7\xbe\x55\x51\x38\x7a\x98\xba\x97\x7c\x73\x2d\x08\x0d" + "\xcb\x0f\x29\xa0\x48\xe3\x65\x69\x12\xc6\x53\x3e\x32\xee\x7a\xed" + "\x29\xb7\x21\x76\x9c\xe6\x4e\x43\xd5\x71\x33\xb0\x74\xd8\x39\xd5" + "\x31\xed\x1f\x28\x51\x0a\xfb\x45\xac\xe1\x0a\x1f\x4b\x79\x4d\x6f" + } + } + }, + { + "ChaCha20 256 bit, TC2", + GCRY_CIPHER_CHACHA20, 32, 8, + "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00", + { + { 128, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\xc5\xd3\x0a\x7c\xe1\xec\x11\x93\x78\xc8\x4f\x48\x7d\x77\x5a\x85" + "\x42\xf1\x3e\xce\x23\x8a\x94\x55\xe8\x22\x9e\x88\x8d\xe8\x5b\xbd" + "\x29\xeb\x63\xd0\xa1\x7a\x5b\x99\x9b\x52\xda\x22\xbe\x40\x23\xeb" + "\x07\x62\x0a\x54\xf6\xfa\x6a\xd8\x73\x7b\x71\xeb\x04\x64\xda\xc0" + "\x10\xf6\x56\xe6\xd1\xfd\x55\x05\x3e\x50\xc4\x87\x5c\x99\x30\xa3" + "\x3f\x6d\x02\x63\xbd\x14\xdf\xd6\xab\x8c\x70\x52\x1c\x19\x33\x8b" + "\x23\x08\xb9\x5c\xf8\xd0\xbb\x7d\x20\x2d\x21\x02\x78\x0e\xa3\x52" + "\x8f\x1c\xb4\x85\x60\xf7\x6b\x20\xf3\x82\xb9\x42\x50\x0f\xce\xac" + } + } + }, + { + "ChaCha20 256 bit, TC3", + GCRY_CIPHER_CHACHA20, 32, 8, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x01\x00\x00\x00\x00\x00\x00\x00", + { + { 128, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\xef\x3f\xdf\xd6\xc6\x15\x78\xfb\xf5\xcf\x35\xbd\x3d\xd3\x3b\x80" + "\x09\x63\x16\x34\xd2\x1e\x42\xac\x33\x96\x0b\xd1\x38\xe5\x0d\x32" + "\x11\x1e\x4c\xaf\x23\x7e\xe5\x3c\xa8\xad\x64\x26\x19\x4a\x88\x54" + "\x5d\xdc\x49\x7a\x0b\x46\x6e\x7d\x6b\xbd\xb0\x04\x1b\x2f\x58\x6b" + "\x53\x05\xe5\xe4\x4a\xff\x19\xb2\x35\x93\x61\x44\x67\x5e\xfb\xe4" + "\x40\x9e\xb7\xe8\xe5\xf1\x43\x0f\x5f\x58\x36\xae\xb4\x9b\xb5\x32" + "\x8b\x01\x7c\x4b\x9d\xc1\x1f\x8a\x03\x86\x3f\xa8\x03\xdc\x71\xd5" + "\x72\x6b\x2b\x6b\x31\xaa\x32\x70\x8a\xfe\x5a\xf1\xd6\xb6\x90\x58" + } + } + }, + { + "ChaCha20 256 bit, TC4", + GCRY_CIPHER_CHACHA20, 32, 8, + "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" + "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", + "\xff\xff\xff\xff\xff\xff\xff\xff", + { + { 128, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\xd9\xbf\x3f\x6b\xce\x6e\xd0\xb5\x42\x54\x55\x77\x67\xfb\x57\x44" + "\x3d\xd4\x77\x89\x11\xb6\x06\x05\x5c\x39\xcc\x25\xe6\x74\xb8\x36" + "\x3f\xea\xbc\x57\xfd\xe5\x4f\x79\x0c\x52\xc8\xae\x43\x24\x0b\x79" + "\xd4\x90\x42\xb7\x77\xbf\xd6\xcb\x80\xe9\x31\x27\x0b\x7f\x50\xeb" + "\x5b\xac\x2a\xcd\x86\xa8\x36\xc5\xdc\x98\xc1\x16\xc1\x21\x7e\xc3" + "\x1d\x3a\x63\xa9\x45\x13\x19\xf0\x97\xf3\xb4\xd6\xda\xb0\x77\x87" + "\x19\x47\x7d\x24\xd2\x4b\x40\x3a\x12\x24\x1d\x7c\xca\x06\x4f\x79" + "\x0f\x1d\x51\xcc\xaf\xf6\xb1\x66\x7d\x4b\xbc\xa1\x95\x8c\x43\x06" + } + } + }, + { + "ChaCha20 256 bit, TC5", + GCRY_CIPHER_CHACHA20, 32, 8, + "\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55" + "\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55", + "\x55\x55\x55\x55\x55\x55\x55\x55", + { + { 128, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\xbe\xa9\x41\x1a\xa4\x53\xc5\x43\x4a\x5a\xe8\xc9\x28\x62\xf5\x64" + "\x39\x68\x55\xa9\xea\x6e\x22\xd6\xd3\xb5\x0a\xe1\xb3\x66\x33\x11" + "\xa4\xa3\x60\x6c\x67\x1d\x60\x5c\xe1\x6c\x3a\xec\xe8\xe6\x1e\xa1" + "\x45\xc5\x97\x75\x01\x7b\xee\x2f\xa6\xf8\x8a\xfc\x75\x80\x69\xf7" + "\xe0\xb8\xf6\x76\xe6\x44\x21\x6f\x4d\x2a\x34\x22\xd7\xfa\x36\xc6" + "\xc4\x93\x1a\xca\x95\x0e\x9d\xa4\x27\x88\xe6\xd0\xb6\xd1\xcd\x83" + "\x8e\xf6\x52\xe9\x7b\x14\x5b\x14\x87\x1e\xae\x6c\x68\x04\xc7\x00" + "\x4d\xb5\xac\x2f\xce\x4c\x68\xc7\x26\xd0\x04\xb1\x0f\xca\xba\x86" + } + } + }, + { + "ChaCha20 256 bit, TC6", + GCRY_CIPHER_CHACHA20, 32, 8, + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + { + { 128, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x9a\xa2\xa9\xf6\x56\xef\xde\x5a\xa7\x59\x1c\x5f\xed\x4b\x35\xae" + "\xa2\x89\x5d\xec\x7c\xb4\x54\x3b\x9e\x9f\x21\xf5\xe7\xbc\xbc\xf3" + "\xc4\x3c\x74\x8a\x97\x08\x88\xf8\x24\x83\x93\xa0\x9d\x43\xe0\xb7" + "\xe1\x64\xbc\x4d\x0b\x0f\xb2\x40\xa2\xd7\x21\x15\xc4\x80\x89\x06" + "\x72\x18\x44\x89\x44\x05\x45\xd0\x21\xd9\x7e\xf6\xb6\x93\xdf\xe5" + "\xb2\xc1\x32\xd4\x7e\x6f\x04\x1c\x90\x63\x65\x1f\x96\xb6\x23\xe6" + "\x2a\x11\x99\x9a\x23\xb6\xf7\xc4\x61\xb2\x15\x30\x26\xad\x5e\x86" + "\x6a\x2e\x59\x7e\xd0\x7b\x84\x01\xde\xc6\x3a\x09\x34\xc6\xb2\xa9" + } + } + }, + { + "ChaCha20 256 bit, TC7", + GCRY_CIPHER_CHACHA20, 32, 8, + "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff" + "\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00", + "\x0f\x1e\x2d\x3c\x4b\x5a\x69\x78", + { + { 128, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x9f\xad\xf4\x09\xc0\x08\x11\xd0\x04\x31\xd6\x7e\xfb\xd8\x8f\xba" + "\x59\x21\x8d\x5d\x67\x08\xb1\xd6\x85\x86\x3f\xab\xbb\x0e\x96\x1e" + "\xea\x48\x0f\xd6\xfb\x53\x2b\xfd\x49\x4b\x21\x51\x01\x50\x57\x42" + "\x3a\xb6\x0a\x63\xfe\x4f\x55\xf7\xa2\x12\xe2\x16\x7c\xca\xb9\x31" + "\xfb\xfd\x29\xcf\x7b\xc1\xd2\x79\xed\xdf\x25\xdd\x31\x6b\xb8\x84" + "\x3d\x6e\xde\xe0\xbd\x1e\xf1\x21\xd1\x2f\xa1\x7c\xbc\x2c\x57\x4c" + "\xcc\xab\x5e\x27\x51\x67\xb0\x8b\xd6\x86\xf8\xa0\x9d\xf8\x7e\xc3" + "\xff\xb3\x53\x61\xb9\x4e\xbf\xa1\x3f\xec\x0e\x48\x89\xd1\x8d\xa5" + } + } + }, + { + "ChaCha20 256 bit, TC8", + GCRY_CIPHER_CHACHA20, 32, 8, + "\xc4\x6e\xc1\xb1\x8c\xe8\xa8\x78\x72\x5a\x37\xe7\x80\xdf\xb7\x35" + "\x1f\x68\xed\x2e\x19\x4c\x79\xfb\xc6\xae\xbe\xe1\xa6\x67\x97\x5d", + "\x1a\xda\x31\xd5\xcf\x68\x82\x21", + { + { 128, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\xf6\x3a\x89\xb7\x5c\x22\x71\xf9\x36\x88\x16\x54\x2b\xa5\x2f\x06" + "\xed\x49\x24\x17\x92\x30\x2b\x00\xb5\xe8\xf8\x0a\xe9\xa4\x73\xaf" + "\xc2\x5b\x21\x8f\x51\x9a\xf0\xfd\xd4\x06\x36\x2e\x8d\x69\xde\x7f" + "\x54\xc6\x04\xa6\xe0\x0f\x35\x3f\x11\x0f\x77\x1b\xdc\xa8\xab\x92" + "\xe5\xfb\xc3\x4e\x60\xa1\xd9\xa9\xdb\x17\x34\x5b\x0a\x40\x27\x36" + "\x85\x3b\xf9\x10\xb0\x60\xbd\xf1\xf8\x97\xb6\x29\x0f\x01\xd1\x38" + "\xae\x2c\x4c\x90\x22\x5b\xa9\xea\x14\xd5\x18\xf5\x59\x29\xde\xa0" + "\x98\xca\x7a\x6c\xcf\xe6\x12\x27\x05\x3c\x84\xe4\x9a\x4a\x33\x32" + }, + { 127, + "\xf6\x3a\x89\xb7\x5c\x22\x71\xf9\x36\x88\x16\x54\x2b\xa5\x2f\x06" + "\xed\x49\x24\x17\x92\x30\x2b\x00\xb5\xe8\xf8\x0a\xe9\xa4\x73\xaf" + "\xc2\x5b\x21\x8f\x51\x9a\xf0\xfd\xd4\x06\x36\x2e\x8d\x69\xde\x7f" + "\x54\xc6\x04\xa6\xe0\x0f\x35\x3f\x11\x0f\x77\x1b\xdc\xa8\xab\x92" + "\xe5\xfb\xc3\x4e\x60\xa1\xd9\xa9\xdb\x17\x34\x5b\x0a\x40\x27\x36" + "\x85\x3b\xf9\x10\xb0\x60\xbd\xf1\xf8\x97\xb6\x29\x0f\x01\xd1\x38" + "\xae\x2c\x4c\x90\x22\x5b\xa9\xea\x14\xd5\x18\xf5\x59\x29\xde\xa0" + "\x98\xca\x7a\x6c\xcf\xe6\x12\x27\x05\x3c\x84\xe4\x9a\x4a\x33", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + } + } + }, + /* from draft-nir-cfrg-chacha20-poly1305-02 */ + { + "ChaCha20 256 bit, IV96-bit", + GCRY_CIPHER_CHACHA20, 32, 12, + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", + "\x07\x00\x00\x00\x40\x41\x42\x43\x44\x45\x46\x47", + { + { 64, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x7b\xac\x2b\x25\x2d\xb4\x47\xaf\x09\xb6\x7a\x55\xa4\xe9\x55\x84" + "\x0a\xe1\xd6\x73\x10\x75\xd9\xeb\x2a\x93\x75\x78\x3e\xd5\x53\xff" + "\xa2\x7e\xcc\xde\xad\xdb\x4d\xb4\xd1\x17\x9c\xe4\xc9\x0b\x43\xd8" + "\xbc\xb7\x94\x8c\x4b\x4b\x7d\x8b\x7d\xf6\x27\x39\x32\xa4\x69\x16" + }, + }, + }, +#endif /*USE_CHACHA20*/ }; gcry_cipher_hd_t hde, hdd; @@ -3649,6 +3972,9 @@ check_ciphers (void) GCRY_CIPHER_SALSA20, GCRY_CIPHER_SALSA20R12, #endif +#if USE_CHACHA20 + GCRY_CIPHER_CHACHA20, +#endif 0 }; int i; ----------------------------------------------------------------------- Summary of changes: cipher/Makefile.am | 1 + cipher/chacha20-avx2-amd64.S | 949 +++++++++++++++++++++++++++++++++++++++++ cipher/chacha20-ssse3-amd64.S | 610 ++++++++++++++++++++++++++ cipher/chacha20.c | 544 +++++++++++++++++++++++ cipher/cipher.c | 3 + configure.ac | 16 +- doc/gcrypt.texi | 10 +- src/cipher.h | 1 + src/gcrypt.h.in | 3 +- tests/basic.c | 330 +++++++++++++- 10 files changed, 2460 insertions(+), 7 deletions(-) create mode 100644 cipher/chacha20-avx2-amd64.S create mode 100644 cipher/chacha20-ssse3-amd64.S create mode 100644 cipher/chacha20.c hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Tue May 13 10:50:14 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 13 May 2014 10:50:14 +0200 Subject: [git] gnupg-doc - branch, master, updated. d5981896f2e8068837d2a6b40769880e8ec4607a 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 GnuPG website and other docs". The branch, master has been updated via d5981896f2e8068837d2a6b40769880e8ec4607a (commit) from c0e14feb2ddfc4d1b5ef360fff643db59e671065 (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 d5981896f2e8068837d2a6b40769880e8ec4607a Author: Werner Koch Date: Mon May 12 18:39:45 2014 +0200 Add blog entry on preliminary campaign results. diff --git a/misc/blog.gnupg.org/20140512-rewards-sent.html b/misc/blog.gnupg.org/20140512-rewards-sent.html new file mode 100644 index 0000000..127a6b0 --- /dev/null +++ b/misc/blog.gnupg.org/20140512-rewards-sent.html @@ -0,0 +1,321 @@ + + + + + + TITLE - Blog - GnuPG + + + + ++ + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
  + [GnuPG Logo]  
· English ·     
+
+ + + + + + + + + + + + + + + +
Links + +  
  
 
+
+ + + + + + + + + + + + + + + +
+ + + +
+

Goteo Campaign: Preliminary Results

+
Posted May 12, 2014 by Werner
+ +

+Here is a quick campaign status update: After the t-shirts arrived as +expected the week after Eastern, Mechthilde, Michael, Penny, Rainer, +and me met the other day at the FSFE office in D?sseldorf. Due to +Rainer?s excellent preparation we quickly folded, enveloped, and +stamped about 300 t-shirts and snailed them. Kudos to them for +helping with this task. There are still a few t-shirts we have not +been able to sent because some of our contributors did not reply to +several mails asking for missing address details, or the postmaster +returned them due to faulty addresses. If you expected a t-shirt and +did not receive one, please contact me at accounts at GnuPG dot net. +Most of the stickers have also been snailed but a few are still +pending due to uncertain addresses. +

+ +

+The main GnuPG site is now +accessible via TLS and plain http access is redirected to the https +address. Strict Transport Security (HSTS) has also been enabled. In +the case of problems with TLS the site may still be accessed +non-encrypted via +http://www.tla-friendly.gnupg.org. +

+ +

+To accomplish another promise of the campaign, the website may now be +accessed as TOR hidden service at +http://ic6au7wa3f6naxjq.onion. Being +a well known and intentionally public site, it does not make much +sense to have it as a hidden service. However, if the site is to be +accessed anyway via Tor we can avoid the extra TLS layer and and allow +direct access. Note that lists.gnupg.org and some other services are +not available via an onion address. +

+ +

+Finally here are preliminary financial results of the campaign: +

+ +

+Our contributors donated a total of 37270 Euro. Due to card and +Paypal processing problems we actually received 36732 Euro. The +preliminary costs for running the campaign are 18590 Euros, so +that 18142 Euro are available for the goals. Here is an overview +of the costs: +

+ + + + +++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Goteo fee2939
Paypal fees1152
VAT5212
Campaign manager5390
300 t-shirts1852
Envelopes + postage t-shirts996
Rewards for helper102
360 Stickers342
Envelopes + postage sticker210
Campaign server for 5 months395
 18590
+

+Due to missing or incomplete addresses or no response to our mails +we could not ship about 80 stickers and 15 t-shirts. I spend a +substantial amount of time (at least 4 weeks) with direct campaign +related tasks, which were not included in the original plan. That +plan explained how to spend the money: +

+ + + + +++ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
New website4054
New content910
New website design1435
Releasing 2.16000
 12399
+ +

+The extra 5743 Euro we received will be used for general +maintenance, to cover the unexpected time I had to spend on the +campaign, and for some giveaways to long time GnuPG hackers. +

+ +

+Thank you very much for all your help and please keep on +supporting GnuPG. +

+ +
+ + + + +
 
  
 
+
  +
+ + + + + + + + + + + + +
 Technical resources for this
+ service are sponsered by
 
  + OpenIT +  
+
+ +

+ + Valid XHTML 1.0! +     + + Digital Respect for the Masses +     + + Peace! +     + + Valid CSS! +

+ + + +
+
+ + + + diff --git a/misc/blog.gnupg.org/index.html b/misc/blog.gnupg.org/index.html index 8f3a3eb..4e4849f 100644 --- a/misc/blog.gnupg.org/index.html +++ b/misc/blog.gnupg.org/index.html @@ -71,6 +71,183 @@

GnuPG Blog

+
+ +

Goteo Campaign: Preliminary Results

+
+
Posted May 12, 2014 by Werner
+ +

+ Here is a quick campaign status update: After the t-shirts arrived as + expected the week after Eastern, Mechthilde, Michael, Penny, Rainer, + and me met the other day at the FSFE office in D?sseldorf. Due to + Rainer?s excellent preparation we quickly folded, enveloped, and + stamped about 300 t-shirts and snailed them. Kudos to them for + helping with this task. There are still a few t-shirts we have not + been able to sent because some of our contributors did not reply to + several mails asking for missing address details, or the postmaster + returned them due to faulty addresses. If you expected a t-shirt and + did not receive one, please contact me at accounts at GnuPG dot net. + Most of the stickers have also been snailed but a few are still + pending due to uncertain addresses. +

+ +

+ The main GnuPG site is now + accessible via TLS and plain http access is redirected to the https + address. Strict Transport Security (HSTS) has also been enabled. + In the case of problems with TLS the site may still be accessed + non-encrypted via + http://www.tla-friendly.gnupg.org. +

+ +

+ To accomplish another promise of the campaign, the website may now be + accessed as TOR hidden service at + http://ic6au7wa3f6naxjq.onion. Being + a well known and intentionally public site, it does not make much + sense to have it as a hidden service. However, if the site is to be + accessed anyway via Tor we can avoid the extra TLS layer and and + allow direct access. Note that lists.gnupg.org and some other + services are not available via an onion address. +

+ +

+ Finally here are preliminary financial results of the campaign: +

+ +

+ Our contributors donated a total of 37270 Euro. Due to card and + Paypal processing problems we actually received 36732 Euro. The + preliminary costs for running the campaign are 18590 Euros, so + that 18142 Euro are available for the goals. Here is an overview + of the costs: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Goteo fee2939
Paypal fees1152
VAT5212
Campaign manager5390
300 t-shirts1852
Envelopes + postage t-shirts996
Rewards for helper102
360 Stickers342
Envelopes + postage sticker210
Campaign server for 5 months395
 18590
+

+ Due to missing or incomplete addresses or no response to our mails + we could not ship about 80 stickers and 15 t-shirts. I spend a + substantial amount of time (at least 4 weeks) with direct campaign + related tasks, which were not included in the original plan. That + plan explained how to spend the money: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
New website4054
New content910
New website design1435
Releasing 2.16000
 12399
+ +

+ The extra 5743 Euro we received will be used for general + maintenance, to cover the unexpected time I had to spend on the + campaign, and for some giveaways to long time GnuPG hackers. +

+ +

+ Thank you very much for all your help and please keep on + supporting GnuPG. +

+

+
+
diff --git a/web/index.org b/web/index.org index 09e5cc8..020e0af 100644 --- a/web/index.org +++ b/web/index.org @@ -44,6 +44,11 @@ all [[file:news.org][news of previous years]] is also available. # GnuPG's latest news are available as [[http://feedvalidator.org/check.cgi?url%3Dhttps://www.gnupg.org/news.en.rss][RSS 2.0 compliant]] feed. Just # point or paste the [[news.en.rss][RSS file]] into your aggregator. +** Goteo campaign: preliminary results (2014-05-12) + +The blog has a report on the current status of the campaign including +an overview of the financial results. [[https://www.gnupg.org/blog/20140512-rewards-sent.html][{read here}]] + ** Mission complete: campaign ends, closing stats (2014-02-06) After 50 days of crowdfunding, the GnuPG campaign for new website and @@ -51,6 +56,7 @@ infrastructure will close tomorrow. That means rewards for backers can now be ordered and preparations for dispatch can begin. Here are the results so far. [[https://www.gnupg.org/blog/20140206-crowdfunding-complete.html][{more}]] + ** 16 Years of protecting privacy (2013-12-20) Today marks 16 years since the first release of GnuPG. In that time ----------------------------------------------------------------------- Summary of changes: misc/blog.gnupg.org/20140512-rewards-sent.html | 321 ++++++++++++++++++++++++ misc/blog.gnupg.org/index.html | 177 +++++++++++++ web/index.org | 6 + 3 files changed, 504 insertions(+) create mode 100644 misc/blog.gnupg.org/20140512-rewards-sent.html hooks/post-receive -- The GnuPG website and other docs http://git.gnupg.org From cvs at cvs.gnupg.org Tue May 13 16:10:17 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 13 May 2014 16:10:17 +0200 Subject: [git] GPGME - branch, master, updated. gpgme-1.4.3-30-gde6caee 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 de6caeed6d6432101c673c35717f152d5facf823 (commit) from 88f15336ec0eadde68ff2618349efb9006b8e801 (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 de6caeed6d6432101c673c35717f152d5facf823 Author: Werner Koch Date: Tue May 13 15:44:52 2014 +0200 Add 6 new GPGME_STATUS_ codes. * src/status-table.c: Also add missing DECRYPTION_INFO entry. diff --git a/NEWS b/NEWS index 9433356..3eaca19 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,12 @@ Noteworthy changes in version 1.5.0 (unreleased) GPGME_PK_ECC NEW. GPGME_MD_SHA224 NEW. gpgme_subkey_t EXTENDED: New field curve. + GPGME_STATUS_PLAINTEXT_LENGTH NEW. + GPGME_STATUS_MOUNTPOINT NEW. + GPGME_STATUS_PINENTRY_LAUNCHED NEW. + GPGME_STATUS_ATTRIBUTE NEW. + GPGME_STATUS_BEGIN_SIGNING NEW. + GPGME_STATUS_KEY_NOT_CREATED NEW. Noteworthy changes in version 1.4.3 (2013-08-12) diff --git a/src/gpgme.h.in b/src/gpgme.h.in index 170d7dd..d47f4ba 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -455,7 +455,7 @@ typedef enum GPGME_STATUS_BADARMOR = 7, - GPGME_STATUS_RSA_OR_IDEA = 8, + GPGME_STATUS_RSA_OR_IDEA = 8, /* (legacy) */ GPGME_STATUS_KEYEXPIRED = 9, GPGME_STATUS_KEYREVOKED = 10, @@ -465,10 +465,10 @@ typedef enum GPGME_STATUS_TRUST_FULLY = 14, GPGME_STATUS_TRUST_ULTIMATE = 15, - GPGME_STATUS_SHM_INFO = 16, - GPGME_STATUS_SHM_GET = 17, - GPGME_STATUS_SHM_GET_BOOL = 18, - GPGME_STATUS_SHM_GET_HIDDEN = 19, + GPGME_STATUS_SHM_INFO = 16, /* (legacy) */ + GPGME_STATUS_SHM_GET = 17, /* (legacy) */ + GPGME_STATUS_SHM_GET_BOOL = 18, /* (legacy) */ + GPGME_STATUS_SHM_GET_HIDDEN = 19, /* (legacy) */ GPGME_STATUS_NEED_PASSPHRASE = 20, GPGME_STATUS_VALIDSIG = 21, @@ -510,15 +510,15 @@ typedef enum GPGME_STATUS_NOTATION_NAME = 55, GPGME_STATUS_NOTATION_DATA = 56, GPGME_STATUS_POLICY_URL = 57, - GPGME_STATUS_BEGIN_STREAM = 58, - GPGME_STATUS_END_STREAM = 59, + GPGME_STATUS_BEGIN_STREAM = 58, /* (legacy) */ + GPGME_STATUS_END_STREAM = 59, /* (legacy) */ GPGME_STATUS_KEY_CREATED = 60, GPGME_STATUS_USERID_HINT = 61, GPGME_STATUS_UNEXPECTED = 62, GPGME_STATUS_INV_RECP = 63, GPGME_STATUS_NO_RECP = 64, GPGME_STATUS_ALREADY_SIGNED = 65, - GPGME_STATUS_SIGEXPIRED = 66, + GPGME_STATUS_SIGEXPIRED = 66, /* (legacy) */ GPGME_STATUS_EXPSIG = 67, GPGME_STATUS_EXPKEYSIG = 68, GPGME_STATUS_TRUNCATED = 69, @@ -537,7 +537,13 @@ typedef enum GPGME_STATUS_INV_SGNR = 82, GPGME_STATUS_NO_SGNR = 83, GPGME_STATUS_SUCCESS = 84, - GPGME_STATUS_DECRYPTION_INFO = 85 + GPGME_STATUS_DECRYPTION_INFO = 85, + GPGME_STATUS_PLAINTEXT_LENGTH = 86, + GPGME_STATUS_MOUNTPOINT = 87, + GPGME_STATUS_PINENTRY_LAUNCHED = 88, + GPGME_STATUS_ATTRIBUTE = 89, + GPGME_STATUS_BEGIN_SIGNING = 90, + GPGME_STATUS_KEY_NOT_CREATED = 91 } gpgme_status_code_t; diff --git a/src/status-table.c b/src/status-table.c index 8060bdb..b936997 100644 --- a/src/status-table.c +++ b/src/status-table.c @@ -39,17 +39,21 @@ struct status_table_s { sorted at start up, too. */ static struct status_table_s status_table[] = { + { "ABORT", GPGME_STATUS_ABORT }, { "ALREADY_SIGNED", GPGME_STATUS_ALREADY_SIGNED }, + { "ATTRIBUTE", GPGME_STATUS_ATTRIBUTE }, { "BACKUP_KEY_CREATED", GPGME_STATUS_BACKUP_KEY_CREATED }, + { "BAD_PASSPHRASE", GPGME_STATUS_BAD_PASSPHRASE }, { "BADARMOR", GPGME_STATUS_BADARMOR }, { "BADMDC", GPGME_STATUS_BADMDC }, { "BADSIG", GPGME_STATUS_BADSIG }, - { "BAD_PASSPHRASE", GPGME_STATUS_BAD_PASSPHRASE }, { "BEGIN_DECRYPTION", GPGME_STATUS_BEGIN_DECRYPTION }, { "BEGIN_ENCRYPTION", GPGME_STATUS_BEGIN_ENCRYPTION }, + { "BEGIN_SIGNING", GPGME_STATUS_BEGIN_SIGNING }, { "BEGIN_STREAM", GPGME_STATUS_BEGIN_STREAM }, { "CARDCTRL", GPGME_STATUS_CARDCTRL }, { "DECRYPTION_FAILED", GPGME_STATUS_DECRYPTION_FAILED }, + { "DECRYPTION_INFO", GPGME_STATUS_DECRYPTION_INFO }, { "DECRYPTION_OKAY", GPGME_STATUS_DECRYPTION_OKAY }, { "DELETE_PROBLEM", GPGME_STATUS_DELETE_PROBLEM }, { "ENC_TO", GPGME_STATUS_ENC_TO }, @@ -68,35 +72,39 @@ static struct status_table_s status_table[] = { "GET_BOOL", GPGME_STATUS_GET_BOOL }, { "GET_HIDDEN", GPGME_STATUS_GET_HIDDEN }, { "GET_LINE", GPGME_STATUS_GET_LINE }, + { "GOOD_PASSPHRASE", GPGME_STATUS_GOOD_PASSPHRASE }, { "GOODMDC", GPGME_STATUS_GOODMDC }, { "GOODSIG", GPGME_STATUS_GOODSIG }, - { "GOOD_PASSPHRASE", GPGME_STATUS_GOOD_PASSPHRASE }, { "GOT_IT", GPGME_STATUS_GOT_IT }, - { "IMPORTED", GPGME_STATUS_IMPORTED }, { "IMPORT_OK", GPGME_STATUS_IMPORT_OK }, { "IMPORT_PROBLEM", GPGME_STATUS_IMPORT_PROBLEM }, { "IMPORT_RES", GPGME_STATUS_IMPORT_RES }, + { "IMPORTED", GPGME_STATUS_IMPORTED }, { "INV_RECP", GPGME_STATUS_INV_RECP }, { "INV_SGNR", GPGME_STATUS_INV_SGNR }, + { "KEY_CREATED", GPGME_STATUS_KEY_CREATED }, + { "KEY_NOT_CREATED", GPGME_STATUS_KEY_NOT_CREATED }, { "KEYEXPIRED", GPGME_STATUS_KEYEXPIRED }, { "KEYREVOKED", GPGME_STATUS_KEYREVOKED }, - { "KEY_CREATED", GPGME_STATUS_KEY_CREATED }, { "LEAVE", GPGME_STATUS_LEAVE }, { "MISSING_PASSPHRASE", GPGME_STATUS_MISSING_PASSPHRASE }, + { "MOUNTPOINT", GPGME_STATUS_MOUNTPOINT }, { "NEED_PASSPHRASE", GPGME_STATUS_NEED_PASSPHRASE }, { "NEED_PASSPHRASE_PIN", GPGME_STATUS_NEED_PASSPHRASE_PIN }, { "NEED_PASSPHRASE_SYM", GPGME_STATUS_NEED_PASSPHRASE_SYM }, { "NEWSIG", GPGME_STATUS_NEWSIG }, - { "NODATA", GPGME_STATUS_NODATA }, - { "NOTATION_DATA", GPGME_STATUS_NOTATION_DATA }, - { "NOTATION_NAME", GPGME_STATUS_NOTATION_NAME }, { "NO_PUBKEY", GPGME_STATUS_NO_PUBKEY }, { "NO_RECP", GPGME_STATUS_NO_RECP }, { "NO_SECKEY", GPGME_STATUS_NO_SECKEY }, { "NO_SGNR", GPGME_STATUS_NO_SGNR }, + { "NODATA", GPGME_STATUS_NODATA }, + { "NOTATION_DATA", GPGME_STATUS_NOTATION_DATA }, + { "NOTATION_NAME", GPGME_STATUS_NOTATION_NAME }, + { "PINENTRY_LAUNCHED", GPGME_STATUS_PINENTRY_LAUNCHED}, { "PKA_TRUST_BAD", GPGME_STATUS_PKA_TRUST_BAD }, { "PKA_TRUST_GOOD", GPGME_STATUS_PKA_TRUST_GOOD }, { "PLAINTEXT", GPGME_STATUS_PLAINTEXT }, + { "PLAINTEXT_LENGTH", GPGME_STATUS_PLAINTEXT_LENGTH }, { "POLICY_URL", GPGME_STATUS_POLICY_URL }, { "PROGRESS", GPGME_STATUS_PROGRESS }, { "REVKEYSIG", GPGME_STATUS_REVKEYSIG }, @@ -108,10 +116,10 @@ static struct status_table_s status_table[] = { "SHM_GET_BOOL", GPGME_STATUS_SHM_GET_BOOL }, { "SHM_GET_HIDDEN", GPGME_STATUS_SHM_GET_HIDDEN }, { "SHM_INFO", GPGME_STATUS_SHM_INFO }, - { "SIGEXPIRED", GPGME_STATUS_SIGEXPIRED }, { "SIG_CREATED", GPGME_STATUS_SIG_CREATED }, { "SIG_ID", GPGME_STATUS_SIG_ID }, { "SIG_SUBPACKET", GPGME_STATUS_SIG_SUBPACKET }, + { "SIGEXPIRED", GPGME_STATUS_SIGEXPIRED }, { "SUCCESS", GPGME_STATUS_SUCCESS }, { "TRUNCATED", GPGME_STATUS_TRUNCATED }, { "TRUST_FULLY", GPGME_STATUS_TRUST_FULLY }, @@ -122,7 +130,6 @@ static struct status_table_s status_table[] = { "UNEXPECTED", GPGME_STATUS_UNEXPECTED }, { "USERID_HINT", GPGME_STATUS_USERID_HINT }, { "VALIDSIG", GPGME_STATUS_VALIDSIG }, - { "ABORT", GPGME_STATUS_ABORT }, {NULL, 0} }; ----------------------------------------------------------------------- Summary of changes: NEWS | 6 ++++++ src/gpgme.h.in | 24 +++++++++++++++--------- src/status-table.c | 25 ++++++++++++++++--------- 3 files changed, 37 insertions(+), 18 deletions(-) hooks/post-receive -- GnuPG Made Easy http://git.gnupg.org From cvs at cvs.gnupg.org Wed May 14 18:10:21 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 14 May 2014 18:10:21 +0200 Subject: [git] GPA - branch, master, updated. gpa-0.9.4-36-g80dd3c0 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 Assistant". The branch, master has been updated via 80dd3c0d4c3b11e2e84dcb55644643f22cbdd8d3 (commit) via f22a7f18e9e02d7a819fdd1b8504bb161472c4ce (commit) via da2dab9ef07bfb9706a853c54d9f6f9094b1bdc2 (commit) via 65a3491a4e9ac4a79de473ba28a5314a13dcfe99 (commit) via b079da56b43cc0191699d0f83778ca3ea1dc8742 (commit) via 7a08aa710b4df95f38bfbbd3509f40f92175397d (commit) via a7da4281e8c515411d66ebd93a280a408bc517a2 (commit) via cfa5b413f38ce21865731b0cf31d552cbdbf5313 (commit) via 107c1465ebd6447ac4ec04a5fd3ca582cf9e5686 (commit) via af81899cf7b7c61ef4fd40b0b2edca3a3f438c74 (commit) from cff74792b61c71a19ca51eb954e3540f2433e9bb (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 80dd3c0d4c3b11e2e84dcb55644643f22cbdd8d3 Author: Werner Koch Date: Wed May 14 18:11:00 2014 +0200 Let OpenPGP specific commands only use OpenPGP keys. * src/gpakeysignop.c (gpa_key_sign_operation_start): Skip non OpenPGP keys. * src/keylist.c (gpa_keylist_get_selected_keys): Add arg optional arg PROTOCOL. Adjust all callers. * src/keymanager.c (key_manager_can_sign): Cehck for OpenPGP. (key_manager_sign, key_manager_trust, key_manager_send): Act only on OpenPGP keys. diff --git a/src/gpakeysignop.c b/src/gpakeysignop.c index 95db5be..ede4be8 100644 --- a/src/gpakeysignop.c +++ b/src/gpakeysignop.c @@ -38,10 +38,10 @@ /* Internal functions */ static gboolean gpa_key_sign_operation_idle_cb (gpointer data); -static void gpa_key_sign_operation_done_error_cb (GpaContext *context, +static void gpa_key_sign_operation_done_error_cb (GpaContext *context, gpg_error_t err, GpaKeySignOperation *op); -static void gpa_key_sign_operation_done_cb (GpaContext *context, +static void gpa_key_sign_operation_done_cb (GpaContext *context, gpg_error_t err, GpaKeySignOperation *op); @@ -98,7 +98,7 @@ static void gpa_key_sign_operation_class_init (GpaKeySignOperationClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - + parent_class = g_type_class_peek_parent (klass); object_class->constructor = gpa_key_sign_operation_constructor; @@ -109,7 +109,7 @@ GType gpa_key_sign_operation_get_type (void) { static GType key_sign_operation_type = 0; - + if (!key_sign_operation_type) { static const GTypeInfo key_sign_operation_info = @@ -124,12 +124,12 @@ gpa_key_sign_operation_get_type (void) 0, /* n_preallocs */ (GInstanceInitFunc) gpa_key_sign_operation_init, }; - - key_sign_operation_type = g_type_register_static + + key_sign_operation_type = g_type_register_static (GPA_KEY_OPERATION_TYPE, "GpaKeySignOperation", &key_sign_operation_info, 0); } - + return key_sign_operation_type; } @@ -141,7 +141,7 @@ GpaKeySignOperation* gpa_key_sign_operation_new (GtkWidget *window, GList *keys) { GpaKeySignOperation *op; - + op = g_object_new (GPA_KEY_SIGN_OPERATION_TYPE, "window", window, "keys", keys, @@ -154,13 +154,15 @@ gpa_key_sign_operation_new (GtkWidget *window, GList *keys) static gpg_error_t gpa_key_sign_operation_start (GpaKeySignOperation *op) -{ +{ gpg_error_t err; gpgme_key_t key; gboolean sign_locally = FALSE; key = gpa_key_operation_current_key (GPA_KEY_OPERATION (op)); g_return_val_if_fail (key, gpg_error (GPG_ERR_CANCELED)); + if (key->protocol != GPGME_PROTOCOL_OpenPGP) + return 0; if (! gpa_key_sign_run_dialog (GPA_OPERATION (op)->window, key, &sign_locally)) @@ -222,9 +224,10 @@ gpa_key_sign_operation_next (GpaKeySignOperation *op) } -static void gpa_key_sign_operation_done_error_cb (GpaContext *context, - gpg_error_t err, - GpaKeySignOperation *op) +static void +gpa_key_sign_operation_done_error_cb (GpaContext *context, + gpg_error_t err, + GpaKeySignOperation *op) { switch (gpg_err_code (err)) { @@ -256,9 +259,10 @@ static void gpa_key_sign_operation_done_error_cb (GpaContext *context, } } -static void gpa_key_sign_operation_done_cb (GpaContext *context, - gpg_error_t err, - GpaKeySignOperation *op) +static void +gpa_key_sign_operation_done_cb (GpaContext *context, + gpg_error_t err, + GpaKeySignOperation *op) { GPA_KEY_OPERATION (op)->current = g_list_next (GPA_KEY_OPERATION (op)->current); diff --git a/src/keylist.c b/src/keylist.c index 2932d41..7a89d92 100644 --- a/src/keylist.c +++ b/src/keylist.c @@ -819,9 +819,11 @@ gpa_keylist_has_single_secret_selection (GpaKeyList *keylist) /* Return a GList of selected keys. The caller must not dereference - the keys as they belong to the caller. */ + the keys as they belong to the caller. Unless PROTOCOL is + GPGME_PROTOCOL_UNKNOWN, only keys matching thhe requested protocol + are returned. */ GList * -gpa_keylist_get_selected_keys (GpaKeyList * keylist) +gpa_keylist_get_selected_keys (GpaKeyList * keylist, gpgme_protocol_t protocol) { GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (keylist)); @@ -843,7 +845,10 @@ gpa_keylist_get_selected_keys (GpaKeyList * keylist) key = g_value_get_pointer (&value); g_value_unset(&value); - keys = g_list_append (keys, key); + /* Fixme: Why don't we ref KEY? */ + if (key && (protocol == GPGME_PROTOCOL_UNKNOWN + || protocol == key->protocol)) + keys = g_list_append (keys, key); } g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL); diff --git a/src/keylist.h b/src/keylist.h index 9e97572..c4382d0 100644 --- a/src/keylist.h +++ b/src/keylist.h @@ -72,10 +72,10 @@ GType gpa_keylist_get_type (void) G_GNUC_CONST; /* Usage flags. */ -#define KEY_USAGE_SIGN 1 /* Good for signatures. */ -#define KEY_USAGE_ENCR 2 /* Good for encryption. */ +#define KEY_USAGE_SIGN 1 /* Good for signatures. */ +#define KEY_USAGE_ENCR 2 /* Good for encryption. */ #define KEY_USAGE_CERT 4 /* Good to certify other keys. */ -#define KEY_USAGE_AUTH 8 /* Good for authentication. */ +#define KEY_USAGE_AUTH 8 /* Good for authentication. */ /* Create a new key list widget. */ @@ -107,7 +107,8 @@ gboolean gpa_keylist_has_single_secret_selection (GpaKeyList * keylist); /* Return a GList of selected keys. The caller must not dereference the keys as they belong to the caller. */ -GList *gpa_keylist_get_selected_keys (GpaKeyList * keylist); +GList *gpa_keylist_get_selected_keys (GpaKeyList *keylist, + gpgme_protocol_t protocol); /* Return the selected key. This function returns NULL if no or more than one key has been selected. */ diff --git a/src/keymanager.c b/src/keymanager.c index 2c73777..7b9fe97 100644 --- a/src/keymanager.c +++ b/src/keymanager.c @@ -373,7 +373,8 @@ register_operation (GpaKeyManager *self, GpaOperation *op) static void key_manager_delete (GtkAction *action, GpaKeyManager *self) { - GList *selection = gpa_keylist_get_selected_keys (self->keylist); + GList *selection = gpa_keylist_get_selected_keys (self->keylist, + GPGME_PROTOCOL_UNKNOWN); GpaKeyDeleteOperation *op = gpa_key_delete_operation_new (GTK_WIDGET (self), selection); register_key_operation (self, GPA_KEY_OPERATION (op)); @@ -423,7 +424,8 @@ key_manager_can_sign (gpointer param) the selected key was already signed with the default key. */ GpaKeyManager *self = param; gpgme_key_t key = key_manager_current_key (self); - result = ! key_has_been_signed (key, default_key); + if (key->protocol == GPGME_PROTOCOL_OpenPGP) + result = ! key_has_been_signed (key, default_key); } else if (default_key && key_manager_has_selection (param)) /* Always allow signing many keys at once. */ @@ -448,9 +450,13 @@ key_manager_sign (GtkAction *action, gpointer param) return; } - selection = gpa_keylist_get_selected_keys (self->keylist); - op = gpa_key_sign_operation_new (GTK_WIDGET (self), selection); - register_key_operation (self, GPA_KEY_OPERATION (op)); + selection = gpa_keylist_get_selected_keys (self->keylist, + GPGME_PROTOCOL_OpenPGP); + if (selection) + { + op = gpa_key_sign_operation_new (GTK_WIDGET (self), selection); + register_key_operation (self, GPA_KEY_OPERATION (op)); + } } /* Invoke the "edit key" dialog. */ @@ -488,9 +494,13 @@ key_manager_trust (GtkAction *action, gpointer param) if (! key_manager_has_single_selection (self)) return; - selection = gpa_keylist_get_selected_keys (self->keylist); - op = gpa_key_trust_operation_new (GTK_WIDGET (self), selection); - register_key_operation (self, GPA_KEY_OPERATION (op)); + selection = gpa_keylist_get_selected_keys (self->keylist, + GPGME_PROTOCOL_OpenPGP); + if (selection) + { + op = gpa_key_trust_operation_new (GTK_WIDGET (self), selection); + register_key_operation (self, GPA_KEY_OPERATION (op)); + } } @@ -514,7 +524,8 @@ key_manager_export (GtkAction *action, gpointer param) GList *selection; GpaExportFileOperation *op; - selection = gpa_keylist_get_selected_keys (self->keylist); + selection = gpa_keylist_get_selected_keys (self->keylist, + GPGME_PROTOCOL_UNKNOWN); if (! selection) return; @@ -551,9 +562,13 @@ key_manager_send (GtkAction *action, gpointer param) if (! key_manager_has_single_selection (self)) return; - selection = gpa_keylist_get_selected_keys (self->keylist); - op = gpa_export_server_operation_new (GTK_WIDGET (self), selection); - register_operation (self, GPA_OPERATION (op)); + selection = gpa_keylist_get_selected_keys (self->keylist, + GPGME_PROTOCOL_OPENPGP); + if (selection) + { + op = gpa_export_server_operation_new (GTK_WIDGET (self), selection); + register_operation (self, GPA_OPERATION (op)); + } } #endif /*ENABLE_KEYSERVER_SUPPORT*/ @@ -643,6 +658,7 @@ key_manager_selection_changed (GtkTreeSelection *treeselection, gpointer param) { GpaKeyManager *self = param; + GList *selection; /* Some other piece of the keyring wants us to ignore this signal. */ if (self->freeze_selection) @@ -661,14 +677,14 @@ key_manager_selection_changed (GtkTreeSelection *treeselection, gpgme_op_keylist_end (self->ctx->ctx); /* Load the new one. */ - if (gpa_keylist_has_single_selection (self->keylist)) + if (gpa_keylist_has_single_selection (self->keylist) + && (selection = gpa_keylist_get_selected_keys (self->keylist, + GPGME_PROTOCOL_UNKNOWN))) { gpg_error_t err; - GList *selection; gpgme_key_t key; int old_mode; - selection = gpa_keylist_get_selected_keys (self->keylist); key = (gpgme_key_t) selection->data; old_mode = gpgme_get_keylist_mode (self->ctx->ctx); @@ -822,7 +838,8 @@ key_manager_copy (GtkAction *action, gpointer param) GList *selection; GpaExportClipboardOperation *op; - selection = gpa_keylist_get_selected_keys (self->keylist); + selection = gpa_keylist_get_selected_keys (self->keylist, + GPGME_PROTOCOL_UNKNOWN); if (! selection) return; @@ -1141,10 +1158,14 @@ idle_update_details (gpointer param) } else { - GList *selection = gpa_keylist_get_selected_keys (self->keylist); - gpa_key_details_update (self->details, NULL, - g_list_length (selection)); - g_list_free (selection); + GList *selection = gpa_keylist_get_selected_keys (self->keylist, + GPGME_PROTOCOL_UNKNOWN); + if (selection) + { + gpa_key_details_update (self->details, NULL, + g_list_length (selection)); + g_list_free (selection); + } } /* Set the idle id to NULL to indicate that the idle handler has commit f22a7f18e9e02d7a819fdd1b8504bb161472c4ce Author: Werner Koch Date: Wed May 14 15:40:32 2014 +0200 w32: Fix directory separator in backup dialog. * src/gpabackupop.c (gpa_backup_operation_dialog_run): Use correct directory separator. diff --git a/src/gpabackupop.c b/src/gpabackupop.c index 4f5ddc7..46aeba3 100644 --- a/src/gpabackupop.c +++ b/src/gpabackupop.c @@ -275,8 +275,10 @@ gpa_backup_operation_dialog_run (GtkWidget *parent, const gchar *key_id, /* Set the default file name. I am not sure whether ".p12" or ".pem" is better for an _armored_ pkcs#12. */ - default_comp = g_strdup_printf ("%s/secret-key-%s.%s", - gnupg_homedir, key_id, + default_comp = g_strdup_printf ("%s%csecret-key-%s.%s", + gnupg_homedir, + G_DIR_SEPARATOR, + key_id, is_x509? "p12":"asc"); gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), default_comp); g_free (default_comp); commit da2dab9ef07bfb9706a853c54d9f6f9094b1bdc2 Author: Werner Koch Date: Wed May 14 14:52:32 2014 +0200 Add command line option --stop-server. * src/gpa.c (main): Implement option. * src/server.c (cmd_kill_uiserver): New. (register_commands): Register new command. diff --git a/src/gpa.c b/src/gpa.c index 4e67bb2..1ff0c5e 100644 --- a/src/gpa.c +++ b/src/gpa.c @@ -69,6 +69,7 @@ typedef struct gboolean start_clipboard; gboolean start_settings; gboolean start_only_server; + gboolean stop_running_server; gboolean disable_x509; gboolean no_remote; gboolean enable_logging; @@ -121,6 +122,8 @@ static GOptionEntry option_entries[] = N_("Read options from file"), "FILE" }, { "no-remote", 0, 0, G_OPTION_ARG_NONE, &args.no_remote, N_("Do not connect to a running instance"), NULL }, + { "stop-server", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, + &args.stop_running_server, NULL, NULL }, /* Note: the cms option will eventually be removed. */ { "cms", 'x', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &cms_hack, NULL, NULL }, @@ -545,8 +548,18 @@ main (int argc, char *argv[]) gpa_options_set_file (gpa_options_get_instance (), configname); g_free (configname); + if (args.stop_running_server) + { + /* If a UI server with the same name is already running, stop + it. If not, do nothing. */ + if (gpa_check_server () == 2) + gpa_send_to_server ("KILL_UISERVER"); + return 0; + } + + /* Check whether we need to start a server or to simply open a - windowin an existing server. */ + window in an already running server. */ switch (gpa_check_server ()) { case 0: /* No running server on the expected socket. Start one. */ diff --git a/src/server.c b/src/server.c index 78bb4b9..023eaf8 100644 --- a/src/server.c +++ b/src/server.c @@ -1583,6 +1583,18 @@ cmd_checksum_verify_files (assuan_context_t ctx, char *line) return assuan_process_done (ctx, err); } + + +/* KILL_UISERVER */ +static gpg_error_t +cmd_kill_uiserver (assuan_context_t ctx, char *line) +{ + (void)line; + shutdown_pending = TRUE; + return assuan_process_done (ctx, 0); +} + + static gpg_error_t reset_notify (assuan_context_t ctx, char *line) @@ -1668,6 +1680,7 @@ register_commands (assuan_context_t ctx) { "IMPORT_FILES", cmd_import_files }, { "CHECKSUM_CREATE_FILES", cmd_checksum_create_files }, { "CHECKSUM_VERIFY_FILES", cmd_checksum_verify_files }, + { "KILL_UISERVER", cmd_kill_uiserver }, { NULL } }; int i, rc; commit 65a3491a4e9ac4a79de473ba28a5314a13dcfe99 Author: Werner Koch Date: Tue May 13 16:13:34 2014 +0200 Fix regression in edit dialogs due to new status lines. * src/gpgmeedit.c (edit_fnc): Ignore pinentry launched status. diff --git a/src/gpgmeedit.c b/src/gpgmeedit.c index 36e8824..7ff9a05 100644 --- a/src/gpgmeedit.c +++ b/src/gpgmeedit.c @@ -214,6 +214,7 @@ edit_fnc (void *opaque, gpgme_status_code_t status, || status == GPGME_STATUS_BACKUP_KEY_CREATED || status == GPGME_STATUS_CARDCTRL /* Issued by gpg1. */ || status == GPGME_STATUS_SC_OP_SUCCESS + || status == GPGME_STATUS_PINENTRY_LAUNCHED || status == GPGME_STATUS_PROGRESS) { return parms->err; commit b079da56b43cc0191699d0f83778ca3ea1dc8742 Author: Werner Koch Date: Tue May 13 14:36:54 2014 +0200 Implement backup of X.509 keys. * src/gpgmetools.c (gpa_backup_key): Add arg is_x509 and support X.509 backups. * src/gpabackupop.c (PROP_PROTOCOL): New. (gpa_backup_operation_get_property): Add it. (gpa_backup_operation_set_property): Add it. (gpa_backup_operation_class_init): Install new property (gpa_backup_operation_finalize): Remove surplus NULL check. (gpa_backup_operation_do_backup): Pass x509 flag to gpa_backup_key. (gpa_backup_operation_dialog_run): Add arg is_x509. Move extra label generation out of the static dialog generation. Use ".p12" for X.509 keys. (gpa_backup_operation_idle_cb): Pass x509 flag to the dialog run call. (gpa_backup_operation_new): Create protocol property from KEY. (gpa_backup_operation_new_from_fpr): Add arg protocol. * src/gpabackupop.h (_GpaBackupOperation): Add field protocol. * src/gpagenkeysimpleop.c (gpa_gen_key_simple_operation_done_cb): Pass PROTOCOL to gpa_backup_operation_new_from_fpr. * src/keymanager.c (key_manager_mapped): Assure that gpa_backup_oepration_new is never called with a NULL key. diff --git a/src/gpabackupop.c b/src/gpabackupop.c index 8a48c03..4f5ddc7 100644 --- a/src/gpabackupop.c +++ b/src/gpabackupop.c @@ -38,6 +38,7 @@ enum PROP_0, PROP_KEY, PROP_FINGERPRINT, + PROP_PROTOCOL }; static void @@ -56,6 +57,10 @@ gpa_backup_operation_get_property (GObject *object, case PROP_FINGERPRINT: g_value_set_string (value, op->fpr); break; + case PROP_PROTOCOL: + g_value_set_int (value, op->protocol); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -93,6 +98,9 @@ gpa_backup_operation_set_property (GObject *object, op->key_id = g_strdup (fpr + strlen (fpr) - 8); } break; + case PROP_PROTOCOL: + op->protocol = g_value_get_int (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -104,10 +112,7 @@ gpa_backup_operation_finalize (GObject *object) { GpaBackupOperation *op = GPA_BACKUP_OPERATION (object); - if (op->key) - { - gpgme_key_unref (op->key); - } + gpgme_key_unref (op->key); g_free (op->fpr); g_free (op->key_id); @@ -120,6 +125,7 @@ gpa_backup_operation_init (GpaBackupOperation *op) op->key = NULL; op->fpr = NULL; op->key_id = NULL; + op->protocol = GPGME_PROTOCOL_UNKNOWN; } static GObject* @@ -167,6 +173,13 @@ gpa_backup_operation_class_init (GpaBackupOperationClass *klass) ("fpr", "fpr", "Fingerprint", G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property + (object_class, PROP_PROTOCOL, + g_param_spec_int + ("protocol", "Protocol", + "The gpgme protocol used for FPR.", + GPGME_PROTOCOL_OpenPGP, GPGME_PROTOCOL_UNKNOWN, GPGME_PROTOCOL_UNKNOWN, + G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY)); } GType @@ -202,7 +215,7 @@ gpa_backup_operation_get_type (void) static void gpa_backup_operation_do_backup (GpaBackupOperation *op, gchar *filename) { - if (gpa_backup_key (op->fpr, filename)) + if (gpa_backup_key (op->fpr, filename, (op->protocol == GPGME_PROTOCOL_CMS))) { gchar *message; message = g_strdup_printf (_("A copy of your secret key has " @@ -229,17 +242,18 @@ gpa_backup_operation_do_backup (GpaBackupOperation *op, gchar *filename) /* Return the filename in filename encoding. */ static gchar* -gpa_backup_operation_dialog_run (GtkWidget *parent, const gchar *key_id) +gpa_backup_operation_dialog_run (GtkWidget *parent, const gchar *key_id, + int is_x509) { static GtkWidget *dialog; GtkResponseType response; gchar *default_comp; gchar *filename = NULL; + gchar *id_text; + GtkWidget *id_label; if (! dialog) { - gchar *id_text; - GtkWidget *id_label; dialog = gtk_file_chooser_dialog_new (_("Backup key to file"), GTK_WINDOW (parent), @@ -251,16 +265,19 @@ gpa_backup_operation_dialog_run (GtkWidget *parent, const gchar *key_id) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), g_get_home_dir ()); - /* Set the label with more explanations. */ - id_text = g_strdup_printf (_("Generating backup of key: %s"), key_id); - id_label = gtk_label_new (id_text); - g_free (id_text); - gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), id_label); } - /* Set the default file name. */ - default_comp = g_strdup_printf ("%s/secret-key-%s.asc", - gnupg_homedir, key_id); + /* Set the label with more explanations. */ + id_text = g_strdup_printf (_("Generating backup of key: 0x%s"), key_id); + id_label = gtk_label_new (id_text); + g_free (id_text); + gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), id_label); + + /* Set the default file name. I am not sure whether ".p12" or + ".pem" is better for an _armored_ pkcs#12. */ + default_comp = g_strdup_printf ("%s/secret-key-%s.%s", + gnupg_homedir, key_id, + is_x509? "p12":"asc"); gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), default_comp); g_free (default_comp); @@ -284,7 +301,8 @@ gpa_backup_operation_idle_cb (gpointer data) gchar *file; file = gpa_backup_operation_dialog_run (GPA_OPERATION (op)->window, - op->key_id); + op->key_id, + !!(op->protocol==GPGME_PROTOCOL_CMS)); if (file) gpa_backup_operation_do_backup (op, file); @@ -304,19 +322,22 @@ gpa_backup_operation_new (GtkWidget *window, gpgme_key_t key) op = g_object_new (GPA_BACKUP_OPERATION_TYPE, "window", window, "key", key, + "protocol", key->protocol, NULL); return op; } GpaBackupOperation* -gpa_backup_operation_new_from_fpr (GtkWidget *window, const gchar *fpr) +gpa_backup_operation_new_from_fpr (GtkWidget *window, + const gchar *fpr, gpgme_protocol_t protocol) { GpaBackupOperation *op; op = g_object_new (GPA_BACKUP_OPERATION_TYPE, "window", window, "fpr", fpr, + "protocol", protocol, NULL); return op; diff --git a/src/gpabackupop.h b/src/gpabackupop.h index 979d5b4..5002e89 100644 --- a/src/gpabackupop.h +++ b/src/gpabackupop.h @@ -43,6 +43,7 @@ struct _GpaBackupOperation { gpgme_key_t key; gchar *fpr, *key_id; + gpgme_protocol_t protocol; }; struct _GpaBackupOperationClass { @@ -51,11 +52,12 @@ struct _GpaBackupOperationClass { GType gpa_backup_operation_get_type (void) G_GNUC_CONST; -/* API */ -GpaBackupOperation* +/* API */ +GpaBackupOperation* gpa_backup_operation_new (GtkWidget *window, gpgme_key_t key); -GpaBackupOperation* -gpa_backup_operation_new_from_fpr (GtkWidget *window, const gchar *fpr); +GpaBackupOperation* +gpa_backup_operation_new_from_fpr (GtkWidget *window, const gchar *fpr, + gpgme_protocol_t protocol); #endif diff --git a/src/gpagenkeysimpleop.c b/src/gpagenkeysimpleop.c index fd6c21a..a298ac7 100644 --- a/src/gpagenkeysimpleop.c +++ b/src/gpagenkeysimpleop.c @@ -192,7 +192,8 @@ gpa_gen_key_simple_operation_done_cb (GpaContext *context, { GpaBackupOperation *backup; - backup = gpa_backup_operation_new_from_fpr (op->wizard, result->fpr); + backup = gpa_backup_operation_new_from_fpr + (op->wizard, result->fpr, gpgme_get_protocol (context->ctx)); g_signal_connect (backup, "completed", G_CALLBACK (gpa_gen_key_simple_operation_backup_complete), diff --git a/src/gpgmetools.c b/src/gpgmetools.c index 8c16622..621ea23 100644 --- a/src/gpgmetools.c +++ b/src/gpgmetools.c @@ -522,10 +522,11 @@ get_gpg_connect_agent_path (void) /* Backup a key. It exports both the public and secret keys to a file. - Returns TRUE on success and FALSE on error. It displays errors to - the user. */ + IS_X509 tells the function that the fingerprint is from an X.509 + key. Returns TRUE on success and FALSE on error. It displays + errors to the user. */ gboolean -gpa_backup_key (const gchar *fpr, const char *filename) +gpa_backup_key (const gchar *fpr, const char *filename, int is_x509) { gchar *header, *pub_key, *sec_key; gchar *err; @@ -544,17 +545,26 @@ gpa_backup_key (const gchar *fpr, const char *filename) NULL, "--batch", "--no-tty", "--armor", "--export-secret-key", (gchar*) fpr, NULL }; + gchar *seccms_argv[] = + { + NULL, "--batch", "--no-tty", "--armor", "--export-secret-key-p12", + (gchar*) fpr, NULL + }; const gchar *path; mode_t mask; /* Get the gpg path. */ - path = get_gpg_path (); + if (is_x509) + path = get_gpgsm_path (); + else + path = get_gpg_path (); g_return_val_if_fail (path && *path, FALSE); /* Add the executable to the arg arrays */ header_argv[0] = (gchar*) path; pub_argv[0] = (gchar*) path; sec_argv[0] = (gchar*) path; + seccms_argv[0] = (gchar*) path; /* Open the file */ mask = umask (0077); file = g_fopen (filename, "w"); @@ -568,11 +578,13 @@ gpa_backup_key (const gchar *fpr, const char *filename) return FALSE; } /* Get the keys and write them into the file */ - fputs (_("************************************************************************\n" - "* WARNING: This file is a backup of your secret key. Please keep it in *\n" - "* a safe place. *\n" - "************************************************************************\n\n"), - file); + fputs (_( + "************************************************************************\n" + "* WARNING: This file is a backup of your secret key. Please keep it in *\n" + "* a safe place. *\n" + "************************************************************************\n" + "\n"), file); + fputs (_("The key backed up in this file is:\n\n"), file); if( !g_spawn_sync (NULL, header_argv, NULL, 0, NULL, NULL, &header, &err, &ret_code, NULL)) @@ -584,7 +596,7 @@ gpa_backup_key (const gchar *fpr, const char *filename) g_free (header); fputs ("\n", file); if( !g_spawn_sync (NULL, pub_argv, NULL, 0, NULL, NULL, &pub_key, - &err, &ret_code, NULL)) + &err, &ret_code, NULL)) { fclose (file); return FALSE; @@ -593,7 +605,9 @@ gpa_backup_key (const gchar *fpr, const char *filename) g_free (err); g_free (pub_key); fputs ("\n", file); - if( !g_spawn_sync (NULL, sec_argv, NULL, 0, NULL, NULL, &sec_key, + if( !g_spawn_sync (NULL, + is_x509? seccms_argv : sec_argv, + NULL, 0, NULL, NULL, &sec_key, &err, &ret_code, NULL)) { fclose (file); diff --git a/src/gpgmetools.h b/src/gpgmetools.h index 8f08ae8..c6d4885 100644 --- a/src/gpgmetools.h +++ b/src/gpgmetools.h @@ -127,9 +127,10 @@ gpg_error_t gpa_generate_key_start (gpgme_ctx_t ctx, gpa_keygen_para_t *params); /* Backup a key. It exports both the public and secret keys to a - file. Returns TRUE on success and FALSE on error. It displays - errors to the user. */ -gboolean gpa_backup_key (const gchar *fpr, const char *filename); + file. IS_X509 tells the function that the fingerprint is from an + X.509 key. Returns TRUE on success and FALSE on error. It + displays errors to the user. */ +gboolean gpa_backup_key (const gchar *fpr, const char *filename, int is_x509); gpa_keygen_para_t *gpa_keygen_para_new (void); diff --git a/src/keymanager.c b/src/keymanager.c index b9a5dbc..2c73777 100644 --- a/src/keymanager.c +++ b/src/keymanager.c @@ -764,10 +764,15 @@ key_manager_mapped (gpointer param) gtk_widget_destroy (dialog); if (response == GTK_RESPONSE_OK) { - GpaBackupOperation *op = gpa_backup_operation_new - (GTK_WIDGET (self), gpa_options_get_default_key - (gpa_options_get_instance ())); - register_operation (self, GPA_OPERATION (op)); + gpgme_key_t key; + GpaBackupOperation *op; + + key = gpa_options_get_default_key (gpa_options_get_instance ()); + if (key) + { + op = gpa_backup_operation_new (GTK_WIDGET (self), key); + register_operation (self, GPA_OPERATION (op)); + } } asked_about_key_backup = TRUE; } commit 7a08aa710b4df95f38bfbbd3509f40f92175397d Author: Werner Koch Date: Mon May 12 11:59:37 2014 +0200 In the subkey view show tooltips for the entire check box columns. * src/gpasubkeylist.c (query_tooltip_cb): New. (gpa_subkey_list_new): Connect handler. diff --git a/src/gpasubkeylist.c b/src/gpasubkeylist.c index 8e53cac..78e933b 100644 --- a/src/gpasubkeylist.c +++ b/src/gpasubkeylist.c @@ -26,6 +26,13 @@ #include "keytable.h" #include "gpasubkeylist.h" + +static gboolean query_tooltip_cb (GtkWidget *wdiget, int x, int y, + gboolean keyboard_mode, + GtkTooltip *tooltip, gpointer user_data); + + + /* * Implement a List showing the subkeys in a given key */ @@ -154,6 +161,10 @@ gpa_subkey_list_new (void) _("Serial number of the smart card.")); gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); + g_object_set (list, "has-tooltip", TRUE, NULL); + g_signal_connect (list, "query-tooltip", + G_CALLBACK (query_tooltip_cb), list); + return list; } @@ -254,3 +265,32 @@ gpa_subkey_list_set_key (GtkWidget *list, gpgme_key_t key) } } } + + +/* Tooltip display callback. */ +static gboolean +query_tooltip_cb (GtkWidget *widget, int x, int y, gboolean keyboard_tip, + GtkTooltip *tooltip, gpointer user_data) +{ + GtkTreeView *tv = GTK_TREE_VIEW (widget); + GtkTreeViewColumn *column; + char *text; + + (void)user_data; + + if (!gtk_tree_view_get_tooltip_context (tv, &x, &y, keyboard_tip, + NULL, NULL, NULL)) + return FALSE; /* Not at a row - do not show a tooltip. */ + if (!gtk_tree_view_get_path_at_pos (tv, x, y, NULL, &column, NULL, NULL)) + return FALSE; + + widget = gtk_tree_view_column_get_widget (column); + text = widget? gtk_widget_get_tooltip_text (widget) : NULL; + if (!text) + return FALSE; /* No tooltip desired. */ + + gtk_tooltip_set_text (tooltip, text); + g_free (text); + + return TRUE; /* Show tooltip. */ +} commit a7da4281e8c515411d66ebd93a280a408bc517a2 Author: Werner Koch Date: Mon May 12 09:52:14 2014 +0200 Decorate expire date popup window in key generation. * src/gpadatebutton.c (gpa_date_button_clicked): Pass parent window to gtk_dialog_new. Add close button to the dialog. diff --git a/src/gpadatebutton.c b/src/gpadatebutton.c index 6ea1a09..77b2513 100644 --- a/src/gpadatebutton.c +++ b/src/gpadatebutton.c @@ -161,12 +161,20 @@ static void gpa_date_button_clicked (GtkButton *button) { GpaDateButton *self = GPA_DATE_BUTTON (button); + GtkWidget *toplevel; if (!self->dialog) { - self->dialog = gtk_dialog_new (); - gtk_window_set_decorated (GTK_WINDOW (self->dialog), FALSE); - gtk_window_set_modal (GTK_WINDOW (self->dialog), TRUE); + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (self)); + if (!gtk_widget_is_toplevel (toplevel)) + toplevel = NULL; + + self->dialog = gtk_dialog_new_with_buttons + (NULL, + GTK_WINDOW (toplevel), + (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT), + GTK_STOCK_CLOSE, GTK_RESPONSE_REJECT, + NULL); g_signal_connect (self->dialog, "destroy", G_CALLBACK (destroy_cb), self); @@ -183,7 +191,6 @@ gpa_date_button_clicked (GtkButton *button) G_CALLBACK (month_changed_cb), self); gtk_widget_show_all (self->dialog); - } update_widgets (self); commit cfa5b413f38ce21865731b0cf31d552cbdbf5313 Author: Werner Koch Date: Fri May 9 17:23:54 2014 +0200 Use ".asc" for armored detached OpenPGP signatures. * src/gpafilesignop.c (destination_filename): Take care of ARMOR. diff --git a/src/gpafilesignop.c b/src/gpafilesignop.c index ff3a142..5ecef78 100644 --- a/src/gpafilesignop.c +++ b/src/gpafilesignop.c @@ -244,7 +244,7 @@ destination_filename (const gchar *filename, gboolean armor, else if (protocol == GPGME_PROTOCOL_CMS) extension = ".p7s"; else if (sign_type == GPGME_SIG_MODE_DETACH) - extension = ".sig"; + extension = (armor && protocol == GPGME_PROTOCOL_OPENPGP)? ".asc" : ".sig"; else if (sign_type == GPGME_SIG_MODE_CLEAR) extension = ".asc"; else commit 107c1465ebd6447ac4ec04a5fd3ca582cf9e5686 Author: Werner Koch Date: Fri May 9 17:08:10 2014 +0200 Improve detection of detached signature files. * src/gpafileverifyop.c (is_detached_sig): Rewrite and add test for file. -- GnuPG-bug-id: 1637 diff --git a/src/gpafileverifyop.c b/src/gpafileverifyop.c index 5f45308..67fc412 100644 --- a/src/gpafileverifyop.c +++ b/src/gpafileverifyop.c @@ -196,45 +196,48 @@ static gboolean is_detached_sig (const gchar *filename, gchar **signature_file, gchar **signed_file, GtkWidget *window) { - const gchar *sig_extension[] = {".sig", ".sign"}; + const gchar *sig_extension[] = {".sig", ".asc", ".sign"}; int i; gchar *extension; - /* First, check whether this file is a dettached signature */ + + /* First, check whether this file is a detached signature. */ *signed_file = g_strdup (filename); extension = g_strrstr (*signed_file, "."); - if (extension && - (g_str_equal (extension, ".sig") || - g_str_equal (extension, ".sign"))) + if (extension) { - *extension++ = '\0'; - *signature_file = g_strdup (filename); - return TRUE; + for (i = 0; i < DIM (sig_extension); i++) + if (g_str_equal (extension, sig_extension[i])) + { + *extension = '\0'; /* That makes SIGNED_FILE */ + if (g_file_test (*signed_file, G_FILE_TEST_EXISTS)) + { + *signature_file = g_strdup (filename); + return TRUE; + } + g_free (*signed_file); + *signed_file = NULL; + return FALSE; /* signed file does not exist. */ + } } - /* Now, check whether a dettached signature exists for this file */ - else - { - g_free (*signed_file); - *signed_file = NULL; - - for (i = 0; i < sizeof(sig_extension)/sizeof(sig_extension[0]); i++) - { - gchar *sig = g_strconcat (filename, sig_extension[i], NULL); + g_free (*signed_file); + *signed_file = NULL; - if (g_file_test (sig, G_FILE_TEST_EXISTS) && - ask_use_detached_sig (filename, sig, window)) - { - *signed_file = g_strdup (filename); - *signature_file = sig; - return TRUE; - } - else - { - g_free (sig); - } - } - - return FALSE; + /* Now, check whether a detached signature exists for this file */ + for (i = 0; i < DIM (sig_extension); i++) + { + gchar *sig = g_strconcat (filename, sig_extension[i], NULL); + + if (g_file_test (sig, G_FILE_TEST_EXISTS) + && ask_use_detached_sig (filename, sig, window)) + { + *signed_file = g_strdup (filename); + *signature_file = sig; + return TRUE; + } + g_free (sig); } + + return FALSE; } static gboolean commit af81899cf7b7c61ef4fd40b0b2edca3a3f438c74 Author: Werner Koch Date: Thu May 8 20:43:46 2014 +0200 Show the name of the curve and the creation date in the subkey list. * src/gpa-key-details.c (details_page_fill_key): Add curve info. * src/gpasubkeylist.c (SUBKEY_CREATED): Add new column. (gpa_subkey_list_new): Abbreviate some column titles. Print creation date. (gpa_subkey_list_set_key): Set creation date and curve name. diff --git a/src/gpa-key-details.c b/src/gpa-key-details.c index c43c8ca..38d5d3c 100644 --- a/src/gpa-key-details.c +++ b/src/gpa-key-details.c @@ -18,7 +18,7 @@ * along with this program; if not, see . */ -/* +/* This widget is used to display details of a key. */ @@ -31,7 +31,7 @@ #include #include -#include "gpa.h" +#include "gpa.h" #include "convert.h" #include "keytable.h" #include "siglist.h" @@ -42,7 +42,7 @@ /* Object's class definition. */ -struct _GpaKeyDetailsClass +struct _GpaKeyDetailsClass { GtkNotebookClass parent_class; }; @@ -93,7 +93,7 @@ static void gpa_key_details_finalize (GObject *object); -/************************************************************ +/************************************************************ ******************* Implementation ********************* ************************************************************/ @@ -108,7 +108,7 @@ signatures_uid_changed (GtkComboBox *combo, gpointer user_data) { /* Note that we need to subtract one, as the first entry (with index 0 means) "all user names". */ - gpa_siglist_set_signatures + gpa_siglist_set_signatures (kdt->signatures_list, kdt->current_key, gtk_combo_box_get_active (GTK_COMBO_BOX (combo)) - 1); } @@ -123,7 +123,7 @@ details_page_fill_key (GpaKeyDetails *kdt, gpgme_key_t key) gpgme_key_t seckey; char *text; - seckey = gpa_keytable_lookup_key (gpa_keytable_get_secret_instance(), + seckey = gpa_keytable_lookup_key (gpa_keytable_get_secret_instance(), key->subkeys->fpr); if (seckey) { @@ -176,6 +176,13 @@ details_page_fill_key (GpaKeyDetails *kdt, gpgme_key_t key) text = g_strdup_printf (_("%s %u bits"), gpgme_pubkey_algo_name (key->subkeys->pubkey_algo), key->subkeys->length); + if (key->subkeys->curve) + { + char *text2; + text2 = g_strdup_printf ("%s, %s", text, key->subkeys->curve); + g_free (text); + text = text2; + } gtk_label_set_text (GTK_LABEL (kdt->detail_key_type), text); g_free (text); @@ -204,12 +211,12 @@ details_page_fill_num_keys (GpaKeyDetails *kdt, gint num_key) { char *text = g_strdup_printf (ngettext("%d key selected", "%d keys selected", - num_key), num_key); + num_key), num_key); gtk_label_set_text (GTK_LABEL (kdt->details_num_label), text); g_free (text); } - + gtk_widget_show_all (kdt->details_num_label); gtk_widget_hide_all (kdt->details_table); gtk_widget_set_no_show_all (kdt->details_num_label, FALSE); @@ -271,7 +278,7 @@ construct_details_page (GpaKeyDetails *kdt) label = gtk_label_new (""); kdt->details_num_label = label; gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0); - + table = gtk_table_new (2, 7, FALSE); kdt->details_table = table; gtk_box_pack_start (GTK_BOX (vbox), table, TRUE, TRUE, 0); @@ -279,25 +286,25 @@ construct_details_page (GpaKeyDetails *kdt) gtk_table_set_col_spacing (GTK_TABLE (table), 0, 4); table_row = 0; - kdt->detail_public_private = add_details_row + kdt->detail_public_private = add_details_row (table, table_row++, "", TRUE); - kdt->detail_capabilities = add_details_row + kdt->detail_capabilities = add_details_row (table, table_row++, "", TRUE); - kdt->detail_name = add_details_row + kdt->detail_name = add_details_row (table, table_row++, _("User name:"), TRUE); - kdt->detail_key_id = add_details_row + kdt->detail_key_id = add_details_row (table, table_row++, _("Key ID:"), TRUE); - kdt->detail_fingerprint = add_details_row + kdt->detail_fingerprint = add_details_row (table, table_row++, _("Fingerprint:"), TRUE); - kdt->detail_expiry = add_details_row - (table, table_row++, _("Expires at:"), FALSE); - kdt->detail_owner_trust = add_details_row + kdt->detail_expiry = add_details_row + (table, table_row++, _("Expires at:"), FALSE); + kdt->detail_owner_trust = add_details_row (table, table_row++, _("Owner Trust:"), FALSE); - kdt->detail_key_trust = add_details_row + kdt->detail_key_trust = add_details_row (table, table_row++, _("Key validity:"), FALSE); - kdt->detail_key_type = add_details_row + kdt->detail_key_type = add_details_row (table, table_row++, _("Key type:"), FALSE); - kdt->detail_creation = add_details_row + kdt->detail_creation = add_details_row (table, table_row++, _("Created at:"), FALSE); gtk_notebook_append_page (GTK_NOTEBOOK (kdt), scrolled, @@ -318,9 +325,9 @@ build_signatures_page (GpaKeyDetails *kdt, gpgme_key_t key) { if (kdt->signatures_uids) g_signal_handlers_disconnect_by_func - (G_OBJECT (kdt->signatures_uids), + (G_OBJECT (kdt->signatures_uids), G_CALLBACK (signatures_uid_changed), kdt); - + pnum = gtk_notebook_page_num (GTK_NOTEBOOK (kdt), kdt->signatures_page); if (pnum >= 0) gtk_notebook_remove_page (GTK_NOTEBOOK (kdt), pnum); @@ -352,7 +359,7 @@ build_signatures_page (GpaKeyDetails *kdt, gpgme_key_t key) kdt->signatures_uids = gtk_combo_box_new_text (); gtk_box_pack_start (GTK_BOX (hbox), kdt->signatures_uids, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - + /* Connect the signal to update the list of user IDs in the signatures page of the notebook. */ g_signal_connect (G_OBJECT (kdt->signatures_uids), "changed", @@ -382,7 +389,7 @@ build_signatures_page (GpaKeyDetails *kdt, gpgme_key_t key) kdt->signatures_page = vbox; gtk_notebook_append_page (GTK_NOTEBOOK (kdt), vbox, - gtk_label_new + gtk_label_new (kdt->certchain_list? _("Chain"):_("Signatures"))); @@ -396,7 +403,7 @@ build_signatures_page (GpaKeyDetails *kdt, gpgme_key_t key) gpgme_user_id_t uid; GtkComboBox *combo; int i; - + /* Make the combo widget's width shrink as much as possible. This (hopefully) fixes the previous behaviour correctly: displaying a key with slightly longer signed UIDs @@ -413,7 +420,7 @@ build_signatures_page (GpaKeyDetails *kdt, gpgme_key_t key) gtk_combo_box_append_text (combo, uid_string); g_free (uid_string); } - + gpa_siglist_set_signatures (kdt->signatures_list, key, -1); } else @@ -465,10 +472,10 @@ build_subkeys_page (GpaKeyDetails *kdt, gpgme_key_t key) g_object_ref (kdt->subkeys_list); kdt->subkeys_page = vbox; gtk_notebook_append_page (GTK_NOTEBOOK (kdt), kdt->subkeys_page, - gtk_label_new + gtk_label_new (key->protocol == GPGME_PROTOCOL_OpenPGP ? _("Subkeys") : _("Key"))); - + /* Fill this page. */ gpa_subkey_list_set_key (kdt->subkeys_list, key); @@ -487,12 +494,12 @@ ui_mode_changed (GpaOptions *options, gpointer param) build_signatures_page (kdt, NULL); build_subkeys_page (kdt, NULL); } - else + else { build_signatures_page (kdt, kdt->current_key); build_subkeys_page (kdt, kdt->current_key); } - gtk_notebook_set_show_tabs + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (kdt), gtk_notebook_get_n_pages (GTK_NOTEBOOK (kdt)) > 1); gtk_widget_show_all (GTK_WIDGET (kdt)); } @@ -514,7 +521,7 @@ construct_main_widget (GpaKeyDetails *kdt) -/************************************************************ +/************************************************************ ****************** Object Management ******************** ************************************************************/ @@ -524,7 +531,7 @@ gpa_key_details_class_init (void *class_ptr, void *class_data) GpaKeyDetailsClass *klass = class_ptr; parent_class = g_type_class_peek_parent (klass); - + G_OBJECT_CLASS (klass)->finalize = gpa_key_details_finalize; } @@ -540,7 +547,7 @@ gpa_key_details_init (GTypeInstance *instance, void *class_ptr) static void gpa_key_details_finalize (GObject *object) -{ +{ GpaKeyDetails *kdt = GPA_KEY_DETAILS (object); if (kdt->current_key) @@ -573,7 +580,7 @@ GType gpa_key_details_get_type (void) { static GType this_type = 0; - + if (!this_type) { static const GTypeInfo this_info = @@ -588,23 +595,23 @@ gpa_key_details_get_type (void) 0, /* n_preallocs */ gpa_key_details_init }; - + this_type = g_type_register_static (GTK_TYPE_NOTEBOOK, "GpaKeyDetails", &this_info, 0); } - + return this_type; } -/************************************************************ +/************************************************************ ********************** Public API ************************ ************************************************************/ GtkWidget * gpa_key_details_new () { - return GTK_WIDGET (g_object_new (GPA_KEY_DETAILS_TYPE, NULL)); + return GTK_WIDGET (g_object_new (GPA_KEY_DETAILS_TYPE, NULL)); } @@ -636,8 +643,8 @@ gpa_key_details_update (GtkWidget *keydetails, gpgme_key_t key, int keycount) } else pnum = 0; - - + + if (kdt->current_key) { gpgme_key_unref (kdt->current_key); @@ -668,7 +675,7 @@ gpa_key_details_update (GtkWidget *keydetails, gpgme_key_t key, int keycount) build_signatures_page (kdt, NULL); build_subkeys_page (kdt, NULL); } - gtk_notebook_set_show_tabs + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (kdt), gtk_notebook_get_n_pages (GTK_NOTEBOOK (kdt)) > 1); gtk_widget_show_all (keydetails); diff --git a/src/gpasubkeylist.c b/src/gpasubkeylist.c index cdcc057..8e53cac 100644 --- a/src/gpasubkeylist.c +++ b/src/gpasubkeylist.c @@ -35,6 +35,7 @@ typedef enum SUBKEY_ID, SUBKEY_SIZE, SUBKEY_ALGO, + SUBKEY_CREATED, SUBKEY_EXPIRE, SUBKEY_CAN_SIGN, SUBKEY_CAN_CERTIFY, @@ -62,6 +63,7 @@ gpa_subkey_list_new (void) G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, @@ -88,7 +90,7 @@ gpa_subkey_list_new (void) gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes (_("Algorithm"), + column = gtk_tree_view_column_new_with_attributes (_("Algo"), renderer, "text", SUBKEY_ALGO, NULL); @@ -101,7 +103,14 @@ gpa_subkey_list_new (void) gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes (_("Expiry Date"), + column = gtk_tree_view_column_new_with_attributes (_("Created"), + renderer, + "text", SUBKEY_CREATED, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); + + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes (_("Expires"), renderer, "text", SUBKEY_EXPIRE, NULL); @@ -110,38 +119,38 @@ gpa_subkey_list_new (void) renderer = gtk_cell_renderer_toggle_new (); column = gtk_tree_view_column_new_with_attributes (NULL, renderer, "active", SUBKEY_CAN_SIGN, NULL); - gpa_set_column_title (column, _("[S]"), _("Can sign")); + gpa_set_column_title (column, _("S"), _("Can sign")); gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); renderer = gtk_cell_renderer_toggle_new (); - column = gtk_tree_view_column_new_with_attributes + column = gtk_tree_view_column_new_with_attributes (NULL, renderer, "active", SUBKEY_CAN_CERTIFY, NULL); - gpa_set_column_title (column, _("[C]"), _("Can certify")); + gpa_set_column_title (column, _("C"), _("Can certify")); gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); renderer = gtk_cell_renderer_toggle_new (); column = gtk_tree_view_column_new_with_attributes (NULL, renderer, "active", SUBKEY_CAN_ENCRYPT, NULL); - gpa_set_column_title (column, _("[E]"), _("Can encrypt")); + gpa_set_column_title (column, _("E"), _("Can encrypt")); gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); renderer = gtk_cell_renderer_toggle_new (); column = gtk_tree_view_column_new_with_attributes (NULL, renderer, "active", SUBKEY_CAN_AUTHENTICATE, NULL); - gpa_set_column_title (column, _("[A]"), _("Can authenticate")); + gpa_set_column_title (column, _("A"), _("Can authenticate")); gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); renderer = gtk_cell_renderer_toggle_new (); column = gtk_tree_view_column_new_with_attributes (NULL, renderer, "active", SUBKEY_IS_CARDKEY, NULL); - gpa_set_column_title (column, _("[T]"), + gpa_set_column_title (column, _("T"), _("Secret key stored on a smartcard.")); gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (NULL, renderer, "text", SUBKEY_CARD_NUMBER, NULL); - gpa_set_column_title (column, _("Card S/N"), + gpa_set_column_title (column, _("Card S/N"), _("Serial number of the smart card.")); gtk_tree_view_append_column (GTK_TREE_VIEW (list), column); @@ -183,16 +192,16 @@ gpa_subkey_list_set_key (GtkWidget *list, gpgme_key_t key) (GTK_TREE_VIEW (list))); gpgme_subkey_t subkey, secsubkey; gpgme_key_t seckey; - gchar *size; + gchar *p, *size, *expires; /* Empty the list */ gtk_list_store_clear (store); if (key) { - seckey = gpa_keytable_lookup_key + seckey = gpa_keytable_lookup_key (gpa_keytable_get_secret_instance (), key->subkeys->fpr); - + /* Add all the subkeys */ for (subkey = key->subkeys; subkey; subkey = subkey->next) { @@ -202,7 +211,7 @@ gpa_subkey_list_set_key (GtkWidget *list, gpgme_key_t key) { for (secsubkey = seckey->subkeys; secsubkey; secsubkey = secsubkey->next) - if (subkey->fpr && secsubkey->fpr + if (subkey->fpr && secsubkey->fpr && g_str_equal (subkey->fpr, secsubkey->fpr)) break; } @@ -211,15 +220,27 @@ gpa_subkey_list_set_key (GtkWidget *list, gpgme_key_t key) /* Append */ gtk_list_store_append (store, &iter); - size = g_strdup_printf ("%i bits", subkey->length); - gtk_list_store_set + if (subkey->curve) + size = g_strdup (subkey->curve); + else + size = g_strdup_printf ("%i bits", subkey->length); + + /* We only want "never" and not "never expires" but we need + to take care of the ">= 2038" string. */ + expires = gpa_expiry_date_string (subkey->expires); + if (*expires != '>' && (p = strchr (expires, ' '))) + *p = 0; + + gtk_list_store_set (store, &iter, SUBKEY_ID, subkey->keyid+8, SUBKEY_SIZE, size, SUBKEY_ALGO, gpgme_pubkey_algo_name (subkey->pubkey_algo), - SUBKEY_EXPIRE, - gpa_expiry_date_string (subkey->expires), + SUBKEY_CREATED, + gpa_creation_date_string (subkey->timestamp), + SUBKEY_EXPIRE, + expires, SUBKEY_CAN_SIGN, subkey->can_sign, SUBKEY_CAN_CERTIFY, subkey->can_certify, SUBKEY_CAN_ENCRYPT, subkey->can_encrypt, @@ -229,6 +250,7 @@ gpa_subkey_list_set_key (GtkWidget *list, gpgme_key_t key) SUBKEY_STATUS, subkey_status (subkey), -1); g_free (size); - } - } + g_free (expires); + } + } } ----------------------------------------------------------------------- Summary of changes: src/gpa-key-details.c | 89 ++++++++++++++++++++++------------------- src/gpa.c | 15 ++++++- src/gpabackupop.c | 59 +++++++++++++++++++--------- src/gpabackupop.h | 10 +++-- src/gpadatebutton.c | 15 +++++-- src/gpafilesignop.c | 2 +- src/gpafileverifyop.c | 65 +++++++++++++++--------------- src/gpagenkeysimpleop.c | 3 +- src/gpakeysignop.c | 34 +++++++++------- src/gpasubkeylist.c | 100 ++++++++++++++++++++++++++++++++++++++--------- src/gpgmeedit.c | 1 + src/gpgmetools.c | 36 +++++++++++------ src/gpgmetools.h | 7 ++-- src/keylist.c | 11 ++++-- src/keylist.h | 9 +++-- src/keymanager.c | 74 +++++++++++++++++++++++------------ src/server.c | 13 ++++++ 17 files changed, 363 insertions(+), 180 deletions(-) hooks/post-receive -- The GNU Privacy Assistant http://git.gnupg.org From cvs at cvs.gnupg.org Wed May 14 18:17:34 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 14 May 2014 18:17:34 +0200 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-421-g25036ec 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 25036ec6abbc0c9d0003dcfe227724038c35a304 (commit) via 71fa6a35107d4d4547eb9155d7c2612b6a6a16fb (commit) via 455a4a2212302c05095e736b127f647e95714fe7 (commit) via b2945c451d3d3f25ba11a9fe88c6cbf3f88c2fb5 (commit) from 4aeb02562c9db4b96366220b781e2b4fa2d6fd3b (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 25036ec6abbc0c9d0003dcfe227724038c35a304 Author: Werner Koch Date: Wed May 14 16:32:49 2014 +0200 gpg: Fix uninitialized access to search descindex with gpg keyboxes. * kbx/keybox-search.c (keybox_search): Add arg R_DESCINDEX. Chnage both callers. * g10/keydb.c (keydb_search): Always set DESCINDEX. -- This only affects the new keybox for OpenPGP keys in 2.1. The bug exhibited itself by running GPA's backup command on Windows. diff --git a/g10/keydb.c b/g10/keydb.c index 9085012..688c24c 100644 --- a/g10/keydb.c +++ b/g10/keydb.c @@ -1319,6 +1319,9 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, { gpg_error_t rc; + if (descindex) + *descindex = 0; /* Make sure it is always set on return. */ + if (!hd) return gpg_error (GPG_ERR_INV_ARG); @@ -1333,6 +1336,7 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, && keyblock_cache.kid[0] == desc[0].u.kid[0] && keyblock_cache.kid[1] == desc[0].u.kid[1]) { + /* (DESCINDEX is already set). */ if (DBG_CLOCK) log_clock ("keydb_search leave (cached)"); return 0; @@ -1352,7 +1356,8 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, ndesc, descindex); break; case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_search (hd->active[hd->current].u.kb, desc, ndesc); + rc = keybox_search (hd->active[hd->current].u.kb, desc, + ndesc, descindex); break; } if (rc == -1 || gpg_err_code (rc) == GPG_ERR_EOF) diff --git a/kbx/keybox-search.c b/kbx/keybox-search.c index 7980794..ba284f9 100644 --- a/kbx/keybox-search.c +++ b/kbx/keybox-search.c @@ -720,7 +720,8 @@ keybox_search_reset (KEYBOX_HANDLE hd) /* Note: When in ephemeral mode the search function does visit all blobs but in standard mode, blobs flagged as ephemeral are ignored. */ int -keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc) +keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc, + size_t *r_descindex) { int rc; size_t n; @@ -945,6 +946,10 @@ keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc) } continue; found: + /* Record which DESC we matched on. Note this value is only + meaningful if this function returns with no errors. */ + if(r_descindex) + *r_descindex = n; for (n=any_skip?0:ndesc; n < ndesc; n++) { /* if (desc[n].skipfnc */ diff --git a/kbx/keybox.h b/kbx/keybox.h index 5b29437..4c447a5 100644 --- a/kbx/keybox.h +++ b/kbx/keybox.h @@ -83,7 +83,8 @@ int keybox_get_cert (KEYBOX_HANDLE hd, ksba_cert_t *ret_cert); int keybox_get_flags (KEYBOX_HANDLE hd, int what, int idx, unsigned int *value); int keybox_search_reset (KEYBOX_HANDLE hd); -int keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc); +int keybox_search (KEYBOX_HANDLE hd, KEYBOX_SEARCH_DESC *desc, size_t ndesc, + size_t *r_descindex); /*-- keybox-update.c --*/ @@ -109,8 +110,6 @@ int keybox_compress (KEYBOX_HANDLE hd); #if 0 int keybox_locate_writable (KEYBOX_HANDLE hd); -int keybox_search_reset (KEYBOX_HANDLE hd); -int keybox_search (KEYBOX_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc); int keybox_rebuild_cache (void *); #endif diff --git a/sm/keydb.c b/sm/keydb.c index de9c95c..845ebba 100644 --- a/sm/keydb.c +++ b/sm/keydb.c @@ -798,7 +798,7 @@ keydb_search (KEYDB_HANDLE hd, KEYDB_SEARCH_DESC *desc, size_t ndesc) BUG(); /* we should never see it here */ break; case KEYDB_RESOURCE_TYPE_KEYBOX: - rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc); + rc = keybox_search (hd->active[hd->current].u.kr, desc, ndesc, NULL); break; } if (rc == -1) /* EOF -> switch to next resource */ commit 71fa6a35107d4d4547eb9155d7c2612b6a6a16fb Author: Werner Koch Date: Wed May 14 10:26:30 2014 +0200 w32: Make make_absfilename work with drive letters. * common/stringhelp.c (do_make_filename) [HAVE_DRIVE_LETTERS]: Fix. diff --git a/common/stringhelp.c b/common/stringhelp.c index 4d7c3a6..e1ddf2c 100644 --- a/common/stringhelp.c +++ b/common/stringhelp.c @@ -496,7 +496,9 @@ do_make_filename (int xmode, const char *first_part, va_list arg_ptr) { #ifdef HAVE_DRIVE_LETTERS p = strchr (name, ':'); - if (!p) + if (p) + p++; + else p = name; #else p = name; commit 455a4a2212302c05095e736b127f647e95714fe7 Author: Werner Koch Date: Wed May 14 08:55:58 2014 +0200 gpg: Remove useless diagnostic in MDC verification. * g10/decrypt-data.c (decrypt_data): Do not distinguish between a bad MDC packer header and a bad MDC. -- The separate diagnostic was introduced for debugging a problems. For explaining an MDC error a single error message is easier to understand. diff --git a/g10/decrypt-data.c b/g10/decrypt-data.c index 22a6aef..9c6ae73 100644 --- a/g10/decrypt-data.c +++ b/g10/decrypt-data.c @@ -243,14 +243,10 @@ decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek) gcry_md_write (dfx->mdc_hash, dfx->defer, 2); gcry_md_final (dfx->mdc_hash); - if (dfx->defer[0] != '\xd3' || dfx->defer[1] != '\x14' ) - { - log_error("mdc_packet with invalid encoding\n"); - rc = gpg_error (GPG_ERR_INV_PACKET); - } - else if (datalen != 20 - || memcmp (gcry_md_read (dfx->mdc_hash, 0), - dfx->defer+2,datalen )) + if ( dfx->defer[0] != '\xd3' + || dfx->defer[1] != '\x14' + || datalen != 20 + || memcmp (gcry_md_read (dfx->mdc_hash, 0), dfx->defer+2, datalen)) rc = gpg_error (GPG_ERR_BAD_SIGNATURE); /* log_printhex("MDC message:", dfx->defer, 22); */ /* log_printhex("MDC calc:", gcry_md_read (dfx->mdc_hash,0), datalen); */ commit b2945c451d3d3f25ba11a9fe88c6cbf3f88c2fb5 Author: Werner Koch Date: Wed May 14 08:49:37 2014 +0200 gpg: Fix glitch entering a full expiration time. * g10/keygen.c (ask_expire_interval): Get the current time after the prompt. -- This almost avoid that an entered full ISO timestamp is not used as given but off by the time the user required to enter the timestamp. GnuPG-bug-id: 1639 diff --git a/g10/keygen.c b/g10/keygen.c index 314cf9b..0c95435 100644 --- a/g10/keygen.c +++ b/g10/keygen.c @@ -2302,7 +2302,7 @@ ask_expire_interval(int object,const char *def_expire) answer = NULL; for(;;) { - u32 curtime=make_timestamp(); + u32 curtime; xfree(answer); if(object==0) @@ -2326,6 +2326,7 @@ ask_expire_interval(int object,const char *def_expire) } cpr_kill_prompt(); trim_spaces(answer); + curtime = make_timestamp (); interval = parse_expire_string( answer ); if( interval == (u32)-1 ) { ----------------------------------------------------------------------- Summary of changes: common/stringhelp.c | 4 +++- g10/decrypt-data.c | 12 ++++-------- g10/keydb.c | 7 ++++++- g10/keygen.c | 3 ++- kbx/keybox-search.c | 7 ++++++- kbx/keybox.h | 5 ++--- sm/keydb.c | 2 +- 7 files changed, 24 insertions(+), 16 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Fri May 16 19:19:28 2014 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Fri, 16 May 2014 19:19:28 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-73-gc20daee 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 c20daeeb05329bfc6cc2c562cbd4b965291fe0e1 (commit) via a3062db748f272e0f7346e1ed9e0bf7ed61a4eae (commit) via a7d9eeeba632b7eb4a5b15ff17f6565181642f3c (commit) from a39ee7555691d18cae97560f130aaf952bfbd278 (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 c20daeeb05329bfc6cc2c562cbd4b965291fe0e1 Author: Jussi Kivilinna Date: Mon May 12 20:14:32 2014 +0300 chacha20/AVX2: clear upper-halfs of YMM registers on entry * cipher/chacha20-avx2-amd64.S (_gcry_chacha20_amd64_avx2_blocks): Add 'vzeroupper' at beginning. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/chacha20-avx2-amd64.S b/cipher/chacha20-avx2-amd64.S index 0c5f3f9..1f33de8 100644 --- a/cipher/chacha20-avx2-amd64.S +++ b/cipher/chacha20-avx2-amd64.S @@ -42,6 +42,7 @@ .type _gcry_chacha20_amd64_avx2_blocks, at function; _gcry_chacha20_amd64_avx2_blocks: .Lchacha_blocks_avx2_local: + vzeroupper pushq %rbx pushq %rbp pushq %r12 commit a3062db748f272e0f7346e1ed9e0bf7ed61a4eae Author: Jussi Kivilinna Date: Mon May 12 20:11:33 2014 +0300 chacha20/AVX2: check for ENABLE_AVX2_SUPPORT instead of HAVE_GCC_INLINE_ASM_AVX2 * cipher/chacha20.c (USE_AVX2): Enable depending on ENABLE_AVX2_SUPPORT, not HAVE_GCC_INLINE_ASM_AVX2. * cipher/chacha20-avx2-amd64.S: Ditto. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/chacha20-avx2-amd64.S b/cipher/chacha20-avx2-amd64.S index c50a0c0..0c5f3f9 100644 --- a/cipher/chacha20-avx2-amd64.S +++ b/cipher/chacha20-avx2-amd64.S @@ -27,7 +27,7 @@ #include #if defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) && \ - defined(HAVE_GCC_INLINE_ASM_AVX2) && USE_CHACHA20 + defined(ENABLE_AVX2_SUPPORT) && USE_CHACHA20 #ifdef __PIC__ # define RIP (%rip) diff --git a/cipher/chacha20.c b/cipher/chacha20.c index 2ac5a32..e2cf442 100644 --- a/cipher/chacha20.c +++ b/cipher/chacha20.c @@ -57,7 +57,7 @@ /* USE_AVX2 indicates whether to compile with Intel AVX2 code. */ #undef USE_AVX2 #if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) && \ - defined(HAVE_GCC_INLINE_ASM_AVX2) + defined(ENABLE_AVX2_SUPPORT) # define USE_AVX2 1 #endif commit a7d9eeeba632b7eb4a5b15ff17f6565181642f3c Author: Jussi Kivilinna Date: Mon May 12 19:55:35 2014 +0300 chacha20/SSSE3: clear XMM registers after use * cipher/chacha20-ssse3-amd64.S (_gcry_chacha20_amd64_ssse3_blocks): On return, clear XMM registers. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/chacha20-ssse3-amd64.S b/cipher/chacha20-ssse3-amd64.S index aaa7e5b..50c2ff8 100644 --- a/cipher/chacha20-ssse3-amd64.S +++ b/cipher/chacha20-ssse3-amd64.S @@ -594,9 +594,25 @@ _gcry_chacha20_amd64_ssse3_blocks: .Lchacha_blocks_ssse3_done: movdqu %xmm11, 48(%rdi) movq %rbp, %rsp + pxor %xmm15, %xmm15 + pxor %xmm7, %xmm7 + pxor %xmm14, %xmm14 + pxor %xmm6, %xmm6 + pxor %xmm13, %xmm13 + pxor %xmm5, %xmm5 + pxor %xmm12, %xmm12 + pxor %xmm4, %xmm4 popq %rbp popq %rbx movl $(63 + 512 + 16), %eax + pxor %xmm11, %xmm11 + pxor %xmm3, %xmm3 + pxor %xmm10, %xmm10 + pxor %xmm2, %xmm2 + pxor %xmm9, %xmm9 + pxor %xmm1, %xmm1 + pxor %xmm8, %xmm8 + pxor %xmm0, %xmm0 ret .size _gcry_chacha20_amd64_ssse3_blocks,.-_gcry_chacha20_amd64_ssse3_blocks; ----------------------------------------------------------------------- Summary of changes: cipher/chacha20-avx2-amd64.S | 3 ++- cipher/chacha20-ssse3-amd64.S | 16 ++++++++++++++++ cipher/chacha20.c | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Fri May 16 20:22:56 2014 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Fri, 16 May 2014 20:22:56 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-76-ge813958 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 e813958419b0ec4439e6caf07d3b2234cffa2bfa (commit) via 73b3b75c2221a6e3bed4117e0a206a1193acd2ed (commit) via b8794fed68ebe7567f4617141f0996ad290d9120 (commit) from c20daeeb05329bfc6cc2c562cbd4b965291fe0e1 (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 e813958419b0ec4439e6caf07d3b2234cffa2bfa Author: Jussi Kivilinna Date: Sun May 11 12:00:19 2014 +0300 Add Poly1305 based cipher AEAD mode * cipher/Makefile.am: Add 'cipher-poly1305.c'. * cipher/cipher-internal.h (gcry_cipher_handle): Add 'u_mode.poly1305'. (_gcry_cipher_poly1305_encrypt, _gcry_cipher_poly1305_decrypt) (_gcry_cipher_poly1305_setiv, _gcry_cipher_poly1305_authenticate) (_gcry_cipher_poly1305_get_tag, _gcry_cipher_poly1305_check_tag): New. * cipher/cipher-poly1305.c: New. * cipher/cipher.c (_gcry_cipher_open_internal, cipher_setkey) (cipher_reset, cipher_encrypt, cipher_decrypt, _gcry_cipher_setiv) (_gcry_cipher_authenticate, _gcry_cipher_gettag) (_gcry_cipher_checktag): Handle 'GCRY_CIPHER_MODE_POLY1305'. (cipher_setiv): Move handling of 'GCRY_CIPHER_MODE_GCM' to ... (_gcry_cipher_setiv): ... here, as with other modes. * src/gcrypt.h.in: Add 'GCRY_CIPHER_MODE_POLY1305'. * tests/basic.c (_check_poly1305_cipher, check_poly1305_cipher): New. (check_ciphers): Add Poly1305 check. (check_cipher_modes): Call 'check_poly1305_cipher'. * tests/bench-slope.c (bench_gcm_encrypt_do_bench): Rename to bench_aead_... and take nonce as argument. (bench_gcm_decrypt_do_bench, bench_gcm_authenticate_do_bench): Ditto. (bench_gcm_encrypt_do_bench, bench_gcm_decrypt_do_bench) (bench_gcm_authenticate_do_bench, bench_poly1305_encrypt_do_bench) (bench_poly1305_decrypt_do_bench) (bench_poly1305_authenticate_do_bench, poly1305_encrypt_ops) (poly1305_decrypt_ops, poly1305_authenticate_ops): New. (cipher_modes): Add Poly1305. (cipher_bench_one): Add special handling for Poly1305. -- Patch adds Poly1305 based AEAD cipher mode to libgcrypt. ChaCha20 variant of this mode is proposed for use in TLS and ipsec: https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04 http://tools.ietf.org/html/draft-nir-ipsecme-chacha20-poly1305-02 Signed-off-by: Jussi Kivilinna diff --git a/cipher/Makefile.am b/cipher/Makefile.am index a8b86e6..4468647 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -40,7 +40,7 @@ libcipher_la_LIBADD = $(GCRYPT_MODULES) libcipher_la_SOURCES = \ cipher.c cipher-internal.h \ cipher-cbc.c cipher-cfb.c cipher-ofb.c cipher-ctr.c cipher-aeswrap.c \ -cipher-ccm.c cipher-cmac.c cipher-gcm.c \ +cipher-ccm.c cipher-cmac.c cipher-gcm.c cipher-poly1305.c \ cipher-selftest.c cipher-selftest.h \ pubkey.c pubkey-internal.h pubkey-util.c \ md.c \ diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index cdac445..f6bda66 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -20,6 +20,9 @@ #ifndef G10_CIPHER_INTERNAL_H #define G10_CIPHER_INTERNAL_H +#include "./poly1305-internal.h" + + /* The maximum supported size of a block in bytes. */ #define MAX_BLOCKSIZE 16 @@ -154,6 +157,17 @@ struct gcry_cipher_handle } ccm; #endif + /* Mode specific storage for Poly1305 mode. */ + struct { + /* byte counter for AAD and data. */ + u32 bytecount[2]; + + unsigned int aad_finalized:1; + unsigned int bytecount_over_limits:1; + + poly1305_context_t ctx; + } poly1305; + /* Mode specific storage for CMAC mode. */ struct { unsigned int tag:1; /* Set to 1 if tag has been finalized. */ @@ -319,4 +333,28 @@ void _gcry_cipher_gcm_setkey /* */ (gcry_cipher_hd_t c); +/*-- cipher-poly1305.c --*/ +gcry_err_code_t _gcry_cipher_poly1305_encrypt +/* */ (gcry_cipher_hd_t c, + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); +gcry_err_code_t _gcry_cipher_poly1305_decrypt +/* */ (gcry_cipher_hd_t c, + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); +gcry_err_code_t _gcry_cipher_poly1305_setiv +/* */ (gcry_cipher_hd_t c, + const unsigned char *iv, size_t ivlen); +gcry_err_code_t _gcry_cipher_poly1305_authenticate +/* */ (gcry_cipher_hd_t c, + const unsigned char *aadbuf, size_t aadbuflen); +gcry_err_code_t _gcry_cipher_poly1305_get_tag +/* */ (gcry_cipher_hd_t c, + unsigned char *outtag, size_t taglen); +gcry_err_code_t _gcry_cipher_poly1305_check_tag +/* */ (gcry_cipher_hd_t c, + const unsigned char *intag, size_t taglen); +void _gcry_cipher_poly1305_setkey +/* */ (gcry_cipher_hd_t c); + #endif /*G10_CIPHER_INTERNAL_H*/ diff --git a/cipher/cipher-poly1305.c b/cipher/cipher-poly1305.c new file mode 100644 index 0000000..a22ffa3 --- /dev/null +++ b/cipher/cipher-poly1305.c @@ -0,0 +1,296 @@ +/* cipher-pol1305.c - Poly1305 based AEAD cipher mode + * Copyright (C) 2014 Jussi Kivilinna + * + * 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, see . + */ + +#include +#include +#include +#include +#include + +#include "g10lib.h" +#include "cipher.h" +#include "bufhelp.h" +#include "./cipher-internal.h" +#include "./poly1305-internal.h" + + +static inline int +poly1305_bytecounter_add (u32 ctr[2], size_t add) +{ + int overflow = 0; + + if (sizeof(add) > sizeof(u32)) + { + u32 high_add = ((add >> 31) >> 1) & 0xffffffff; + ctr[1] += high_add; + if (ctr[1] < high_add) + overflow = 1; + } + + ctr[0] += add; + if (ctr[0] >= add) + return overflow; + + ctr[1] += 1; + return (ctr[1] < 1) || overflow; +} + + +static void +poly1305_fill_bytecount (gcry_cipher_hd_t c) +{ + u32 lenbuf[2]; + + lenbuf[0] = le_bswap32(c->u_mode.poly1305.bytecount[0]); + lenbuf[1] = le_bswap32(c->u_mode.poly1305.bytecount[1]); + _gcry_poly1305_update (&c->u_mode.poly1305.ctx, (byte*)lenbuf, + sizeof(lenbuf)); + + wipememory(lenbuf, sizeof(lenbuf)); +} + + +static void +poly1305_aad_finish (gcry_cipher_hd_t c) +{ + /* Start of encryption marks end of AAD stream. */ + poly1305_fill_bytecount(c); + + c->u_mode.poly1305.aad_finalized = 1; + + c->u_mode.poly1305.bytecount[0] = 0; + c->u_mode.poly1305.bytecount[1] = 0; +} + + +static gcry_err_code_t +poly1305_set_zeroiv (gcry_cipher_hd_t c) +{ + byte zero[8] = { 0, }; + + return _gcry_cipher_poly1305_setiv (c, zero, sizeof(zero)); +} + + +gcry_err_code_t +_gcry_cipher_poly1305_authenticate (gcry_cipher_hd_t c, + const byte * aadbuf, size_t aadbuflen) +{ + if (c->u_mode.poly1305.bytecount_over_limits) + return GPG_ERR_INV_LENGTH; + if (c->u_mode.poly1305.aad_finalized) + return GPG_ERR_INV_STATE; + if (c->marks.tag) + return GPG_ERR_INV_STATE; + + if (!c->marks.iv) + poly1305_set_zeroiv(c); + + if (poly1305_bytecounter_add(c->u_mode.poly1305.bytecount, aadbuflen)) + { + c->u_mode.poly1305.bytecount_over_limits = 1; + return GPG_ERR_INV_LENGTH; + } + + _gcry_poly1305_update (&c->u_mode.poly1305.ctx, aadbuf, aadbuflen); + + return 0; +} + + +gcry_err_code_t +_gcry_cipher_poly1305_encrypt (gcry_cipher_hd_t c, + byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen) +{ + gcry_err_code_t err; + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + if (c->marks.tag) + return GPG_ERR_INV_STATE; + if (c->u_mode.poly1305.bytecount_over_limits) + return GPG_ERR_INV_LENGTH; + + if (!c->marks.iv) + { + err = poly1305_set_zeroiv(c); + if (err) + return err; + } + + if (!c->u_mode.poly1305.aad_finalized) + poly1305_aad_finish(c); + + if (poly1305_bytecounter_add(c->u_mode.poly1305.bytecount, inbuflen)) + { + c->u_mode.poly1305.bytecount_over_limits = 1; + return GPG_ERR_INV_LENGTH; + } + + c->spec->stencrypt(&c->context.c, outbuf, (byte*)inbuf, inbuflen); + + _gcry_poly1305_update (&c->u_mode.poly1305.ctx, outbuf, inbuflen); + + return 0; +} + + +gcry_err_code_t +_gcry_cipher_poly1305_decrypt (gcry_cipher_hd_t c, + byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen) +{ + gcry_err_code_t err; + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + if (c->marks.tag) + return GPG_ERR_INV_STATE; + if (c->u_mode.poly1305.bytecount_over_limits) + return GPG_ERR_INV_LENGTH; + + if (!c->marks.iv) + { + err = poly1305_set_zeroiv(c); + if (err) + return err; + } + + if (!c->u_mode.poly1305.aad_finalized) + poly1305_aad_finish(c); + + if (poly1305_bytecounter_add(c->u_mode.poly1305.bytecount, inbuflen)) + { + c->u_mode.poly1305.bytecount_over_limits = 1; + return GPG_ERR_INV_LENGTH; + } + + _gcry_poly1305_update (&c->u_mode.poly1305.ctx, inbuf, inbuflen); + + c->spec->stdecrypt(&c->context.c, outbuf, (byte*)inbuf, inbuflen); + return 0; +} + + +static gcry_err_code_t +_gcry_cipher_poly1305_tag (gcry_cipher_hd_t c, + byte * outbuf, size_t outbuflen, int check) +{ + gcry_err_code_t err; + + if (outbuflen < GCRY_GCM_BLOCK_LEN) + return GPG_ERR_BUFFER_TOO_SHORT; + if (c->u_mode.poly1305.bytecount_over_limits) + return GPG_ERR_INV_LENGTH; + + if (!c->marks.iv) + { + err = poly1305_set_zeroiv(c); + if (err) + return err; + } + + if (!c->u_mode.poly1305.aad_finalized) + poly1305_aad_finish(c); + + if (!c->marks.tag) + { + /* Write data-length to poly1305. */ + poly1305_fill_bytecount(c); + + _gcry_poly1305_finish(&c->u_mode.poly1305.ctx, c->u_iv.iv); + + c->marks.tag = 1; + } + + if (check) + return buf_eq_const(outbuf, c->u_iv.iv, outbuflen) ? + GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; + + memcpy (outbuf, c->u_iv.iv, outbuflen); + return GPG_ERR_NO_ERROR; +} + + +gcry_err_code_t +_gcry_cipher_poly1305_get_tag (gcry_cipher_hd_t c, unsigned char *outtag, + size_t taglen) +{ + return _gcry_cipher_poly1305_tag (c, outtag, taglen, 0); +} + +gcry_err_code_t +_gcry_cipher_poly1305_check_tag (gcry_cipher_hd_t c, const unsigned char *intag, + size_t taglen) +{ + return _gcry_cipher_poly1305_tag (c, (unsigned char *) intag, taglen, 1); +} + + +void +_gcry_cipher_poly1305_setkey (gcry_cipher_hd_t c) +{ + c->u_mode.poly1305.bytecount[0] = 0; + c->u_mode.poly1305.bytecount[1] = 0; + + c->u_mode.poly1305.bytecount_over_limits = 0; + c->u_mode.poly1305.aad_finalized = 0; + c->marks.tag = 0; + c->marks.iv = 0; +} + + +gcry_err_code_t +_gcry_cipher_poly1305_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) +{ + byte tmpbuf[64]; /* size of ChaCha20/Salsa20 block */ + gcry_err_code_t err; + + if (!iv && ivlen > 0) + return GPG_ERR_INV_ARG; + + memset(&c->u_mode.poly1305.ctx, 0, sizeof(c->u_mode.poly1305.ctx)); + + c->u_mode.poly1305.bytecount[0] = 0; + c->u_mode.poly1305.bytecount[1] = 0; + + c->u_mode.poly1305.bytecount_over_limits = 0; + c->u_mode.poly1305.aad_finalized = 0; + c->marks.tag = 0; + c->marks.iv = 0; + + /* Set up IV for stream cipher. */ + c->spec->setiv (&c->context.c, iv, ivlen); + + /* Get the first block from ChaCha20/Salsa20. */ + memset(tmpbuf, 0, sizeof(tmpbuf)); + c->spec->stencrypt(&c->context.c, tmpbuf, tmpbuf, sizeof(tmpbuf)); + + /* Use the first 32-bytes as Poly1305 key. */ + err = _gcry_poly1305_init (&c->u_mode.poly1305.ctx, tmpbuf, POLY1305_KEYLEN); + + wipememory(tmpbuf, sizeof(tmpbuf)); + + if (err) + return err; + + c->marks.iv = 1; + return 0; +} diff --git a/cipher/cipher.c b/cipher/cipher.c index 4751302..da59061 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -418,6 +418,15 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle, err = GPG_ERR_INV_CIPHER_MODE; break; + case GCRY_CIPHER_MODE_POLY1305: + if (!spec->stencrypt || !spec->stdecrypt || !spec->setiv) + err = GPG_ERR_INV_CIPHER_MODE; + else if (spec->algo != GCRY_CIPHER_SALSA20 && + spec->algo != GCRY_CIPHER_SALSA20R12 && + spec->algo != GCRY_CIPHER_CHACHA20) + err = GPG_ERR_INV_CIPHER_MODE; + break; + case GCRY_CIPHER_MODE_STREAM: if (!spec->stencrypt || !spec->stdecrypt) err = GPG_ERR_INV_CIPHER_MODE; @@ -611,6 +620,10 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen) _gcry_cipher_gcm_setkey (c); break; + case GCRY_CIPHER_MODE_POLY1305: + _gcry_cipher_poly1305_setkey (c); + break; + default: break; }; @@ -627,10 +640,6 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen) static gcry_err_code_t cipher_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) { - /* GCM has its own IV handler */ - if (c->mode == GCRY_CIPHER_MODE_GCM) - return _gcry_cipher_gcm_setiv (c, iv, ivlen); - /* If the cipher has its own IV handler, we use only this one. This is currently used for stream ciphers requiring a nonce. */ if (c->spec->setiv) @@ -699,6 +708,10 @@ cipher_reset (gcry_cipher_hd_t c) } break; + case GCRY_CIPHER_MODE_POLY1305: + memset (&c->u_mode.poly1305, 0, sizeof c->u_mode.poly1305); + break; + #ifdef HAVE_U64_TYPEDEF case GCRY_CIPHER_MODE_CCM: memset (&c->u_mode.ccm, 0, sizeof c->u_mode.ccm); @@ -811,6 +824,11 @@ cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, rc = _gcry_cipher_gcm_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); break; + case GCRY_CIPHER_MODE_POLY1305: + rc = _gcry_cipher_poly1305_encrypt (c, outbuf, outbuflen, + inbuf, inbuflen); + break; + case GCRY_CIPHER_MODE_STREAM: c->spec->stencrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf, inbuflen); @@ -919,6 +937,11 @@ cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, rc = _gcry_cipher_gcm_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); break; + case GCRY_CIPHER_MODE_POLY1305: + rc = _gcry_cipher_poly1305_decrypt (c, outbuf, outbuflen, + inbuf, inbuflen); + break; + case GCRY_CIPHER_MODE_STREAM: c->spec->stdecrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf, inbuflen); @@ -1000,6 +1023,14 @@ _gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen) rc = _gcry_cipher_ccm_set_nonce (hd, iv, ivlen); break; + case GCRY_CIPHER_MODE_GCM: + rc = _gcry_cipher_gcm_setiv (hd, iv, ivlen); + break; + + case GCRY_CIPHER_MODE_POLY1305: + rc = _gcry_cipher_poly1305_setiv (hd, iv, ivlen); + break; + default: rc = cipher_setiv (hd, iv, ivlen); break; @@ -1050,6 +1081,10 @@ _gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf, rc = _gcry_cipher_gcm_authenticate (hd, abuf, abuflen); break; + case GCRY_CIPHER_MODE_POLY1305: + rc = _gcry_cipher_poly1305_authenticate (hd, abuf, abuflen); + break; + default: log_error ("gcry_cipher_authenticate: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; @@ -1079,6 +1114,10 @@ _gcry_cipher_gettag (gcry_cipher_hd_t hd, void *outtag, size_t taglen) rc = _gcry_cipher_gcm_get_tag (hd, outtag, taglen); break; + case GCRY_CIPHER_MODE_POLY1305: + rc = _gcry_cipher_poly1305_get_tag (hd, outtag, taglen); + break; + default: log_error ("gcry_cipher_gettag: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; @@ -1108,6 +1147,10 @@ _gcry_cipher_checktag (gcry_cipher_hd_t hd, const void *intag, size_t taglen) rc = _gcry_cipher_gcm_check_tag (hd, intag, taglen); break; + case GCRY_CIPHER_MODE_POLY1305: + rc = _gcry_cipher_poly1305_check_tag (hd, intag, taglen); + break; + default: log_error ("gcry_cipher_checktag: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 3145020..bd38a24 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -895,16 +895,17 @@ enum gcry_cipher_algos supported for each algorithm. */ enum gcry_cipher_modes { - GCRY_CIPHER_MODE_NONE = 0, /* Not yet specified. */ - GCRY_CIPHER_MODE_ECB = 1, /* Electronic codebook. */ - GCRY_CIPHER_MODE_CFB = 2, /* Cipher feedback. */ - GCRY_CIPHER_MODE_CBC = 3, /* Cipher block chaining. */ - GCRY_CIPHER_MODE_STREAM = 4, /* Used with stream ciphers. */ - GCRY_CIPHER_MODE_OFB = 5, /* Outer feedback. */ - GCRY_CIPHER_MODE_CTR = 6, /* Counter. */ - GCRY_CIPHER_MODE_AESWRAP= 7, /* AES-WRAP algorithm. */ - GCRY_CIPHER_MODE_CCM = 8, /* Counter with CBC-MAC. */ - GCRY_CIPHER_MODE_GCM = 9 /* Galois Counter Mode. */ + GCRY_CIPHER_MODE_NONE = 0, /* Not yet specified. */ + GCRY_CIPHER_MODE_ECB = 1, /* Electronic codebook. */ + GCRY_CIPHER_MODE_CFB = 2, /* Cipher feedback. */ + GCRY_CIPHER_MODE_CBC = 3, /* Cipher block chaining. */ + GCRY_CIPHER_MODE_STREAM = 4, /* Used with stream ciphers. */ + GCRY_CIPHER_MODE_OFB = 5, /* Outer feedback. */ + GCRY_CIPHER_MODE_CTR = 6, /* Counter. */ + GCRY_CIPHER_MODE_AESWRAP = 7, /* AES-WRAP algorithm. */ + GCRY_CIPHER_MODE_CCM = 8, /* Counter with CBC-MAC. */ + GCRY_CIPHER_MODE_GCM = 9, /* Galois Counter Mode. */ + GCRY_CIPHER_MODE_POLY1305 = 10, /* Poly1305 based AEAD mode. */ }; /* Flags used with the open function. */ diff --git a/tests/basic.c b/tests/basic.c index de10617..9740919 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -1620,6 +1620,320 @@ check_gcm_cipher (void) static void +_check_poly1305_cipher (unsigned int step) +{ + struct tv + { + int algo; + char key[MAX_DATA_LEN]; + char iv[MAX_DATA_LEN]; + int ivlen; + unsigned char aad[MAX_DATA_LEN]; + int aadlen; + unsigned char plaintext[MAX_DATA_LEN]; + int inlen; + char out[MAX_DATA_LEN]; + char tag[MAX_DATA_LEN]; + } tv[] = + { + /* draft-agl-tls-chacha20poly1305-04 */ + { GCRY_CIPHER_CHACHA20, + "\x42\x90\xbc\xb1\x54\x17\x35\x31\xf3\x14\xaf\x57\xf3\xbe\x3b\x50" + "\x06\xda\x37\x1e\xce\x27\x2a\xfa\x1b\x5d\xbd\xd1\x10\x0a\x10\x07", + "\xcd\x7c\xf6\x7b\xe3\x9c\x79\x4a", 8, + "\x87\xe2\x29\xd4\x50\x08\x45\xa0\x79\xc0", 10, + "\x86\xd0\x99\x74\x84\x0b\xde\xd2\xa5\xca", 10, + "\xe3\xe4\x46\xf7\xed\xe9\xa1\x9b\x62\xa4", + "\x67\x7d\xab\xf4\xe3\xd2\x4b\x87\x6b\xb2\x84\x75\x38\x96\xe1\xd6" }, + /* draft-nir-cfrg-chacha20-poly1305-03 */ + { GCRY_CIPHER_CHACHA20, + "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f" + "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", + "\x07\x00\x00\x00\x40\x41\x42\x43\x44\x45\x46\x47", 12, + "\x50\x51\x52\x53\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7", 12, + "Ladies and Gentlemen of the class of '99: If I could offer you " + "only one tip for the future, sunscreen would be it.", 114, + "\xd3\x1a\x8d\x34\x64\x8e\x60\xdb\x7b\x86\xaf\xbc\x53\xef\x7e\xc2" + "\xa4\xad\xed\x51\x29\x6e\x08\xfe\xa9\xe2\xb5\xa7\x36\xee\x62\xd6" + "\x3d\xbe\xa4\x5e\x8c\xa9\x67\x12\x82\xfa\xfb\x69\xda\x92\x72\x8b" + "\x1a\x71\xde\x0a\x9e\x06\x0b\x29\x05\xd6\xa5\xb6\x7e\xcd\x3b\x36" + "\x92\xdd\xbd\x7f\x2d\x77\x8b\x8c\x98\x03\xae\xe3\x28\x09\x1b\x58" + "\xfa\xb3\x24\xe4\xfa\xd6\x75\x94\x55\x85\x80\x8b\x48\x31\xd7\xbc" + "\x3f\xf4\xde\xf0\x8e\x4b\x7a\x9d\xe5\x76\xd2\x65\x86\xce\xc6\x4b" + "\x61\x16", + "\x18\xfb\x11\xa5\x03\x1a\xd1\x3a\x7e\x3b\x03\xd4\x6e\xe3\xa6\xa7" } + }; + + gcry_cipher_hd_t hde, hdd; + unsigned char out[MAX_DATA_LEN]; + unsigned char tag[16]; + int i, keylen; + gcry_error_t err = 0; + size_t pos, poslen; + int byteNum; + + if (verbose) + fprintf (stderr, " Starting POLY1305 checks.\n"); + + for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) + { + if (verbose) + fprintf (stderr, " checking POLY1305 mode for %s [%i]\n", + gcry_cipher_algo_name (tv[i].algo), + tv[i].algo); + err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_POLY1305, 0); + if (!err) + err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_POLY1305, 0); + if (err) + { + fail ("poly1305, gcry_cipher_open failed: %s\n", gpg_strerror (err)); + return; + } + + keylen = gcry_cipher_get_algo_keylen(tv[i].algo); + if (!keylen) + { + fail ("poly1305, gcry_cipher_get_algo_keylen failed\n"); + return; + } + + err = gcry_cipher_setkey (hde, tv[i].key, keylen); + if (!err) + err = gcry_cipher_setkey (hdd, tv[i].key, keylen); + if (err) + { + fail ("poly1305, gcry_cipher_setkey failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + err = gcry_cipher_setiv (hde, tv[i].iv, tv[i].ivlen); + if (!err) + err = gcry_cipher_setiv (hdd, tv[i].iv, tv[i].ivlen); + if (err) + { + fail ("poly1305, gcry_cipher_setiv failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + for (pos = 0; pos < tv[i].aadlen; pos += step) + { + poslen = (pos + step < tv[i].aadlen) ? step : tv[i].aadlen - pos; + + err = gcry_cipher_authenticate(hde, tv[i].aad + pos, poslen); + if (err) + { + fail ("poly1305, gcry_cipher_authenticate (%d) (%d:%d) failed: " + "%s\n", i, pos, step, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + err = gcry_cipher_authenticate(hdd, tv[i].aad + pos, poslen); + if (err) + { + fail ("poly1305, de gcry_cipher_authenticate (%d) (%d:%d) failed: " + "%s\n", i, pos, step, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + } + + for (pos = 0; pos < tv[i].inlen; pos += step) + { + poslen = (pos + step < tv[i].inlen) ? step : tv[i].inlen - pos; + + err = gcry_cipher_encrypt (hde, out + pos, poslen, + tv[i].plaintext + pos, poslen); + if (err) + { + fail ("poly1305, gcry_cipher_encrypt (%d) (%d:%d) failed: %s\n", + i, pos, step, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + } + + if (memcmp (tv[i].out, out, tv[i].inlen)) + fail ("poly1305, encrypt mismatch entry %d (step %d)\n", i, step); + + for (pos = 0; pos < tv[i].inlen; pos += step) + { + poslen = (pos + step < tv[i].inlen) ? step : tv[i].inlen - pos; + + err = gcry_cipher_decrypt (hdd, out + pos, poslen, NULL, 0); + if (err) + { + fail ("poly1305, gcry_cipher_decrypt (%d) (%d:%d) failed: %s\n", + i, pos, step, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + } + + if (memcmp (tv[i].plaintext, out, tv[i].inlen)) + fail ("poly1305, decrypt mismatch entry %d (step %d)\n", i, step); + + err = gcry_cipher_gettag (hde, out, 16); + if (err) + { + fail ("poly1305, gcry_cipher_gettag(%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (memcmp (tv[i].tag, out, 16)) + fail ("poly1305, encrypt tag mismatch entry %d\n", i); + + + err = gcry_cipher_checktag (hdd, out, 16); + if (err) + { + fail ("poly1305, gcry_cipher_checktag(%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + err = gcry_cipher_reset(hde); + if (!err) + err = gcry_cipher_reset(hdd); + if (err) + { + fail ("poly1305, gcry_cipher_reset (%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + /* gcry_cipher_reset clears the IV */ + err = gcry_cipher_setiv (hde, tv[i].iv, tv[i].ivlen); + if (!err) + err = gcry_cipher_setiv (hdd, tv[i].iv, tv[i].ivlen); + if (err) + { + fail ("poly1305, gcry_cipher_setiv failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + /* this time we authenticate, encrypt and decrypt one byte at a time */ + for (byteNum = 0; byteNum < tv[i].aadlen; ++byteNum) + { + err = gcry_cipher_authenticate(hde, tv[i].aad + byteNum, 1); + if (err) + { + fail ("poly1305, gcry_cipher_authenticate (%d) (byte-buf) failed: " + "%s\n", i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + err = gcry_cipher_authenticate(hdd, tv[i].aad + byteNum, 1); + if (err) + { + fail ("poly1305, de gcry_cipher_authenticate (%d) (byte-buf) " + "failed: %s\n", i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + } + + for (byteNum = 0; byteNum < tv[i].inlen; ++byteNum) + { + err = gcry_cipher_encrypt (hde, out+byteNum, 1, + (tv[i].plaintext) + byteNum, + 1); + if (err) + { + fail ("poly1305, gcry_cipher_encrypt (%d) (byte-buf) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + } + + if (memcmp (tv[i].out, out, tv[i].inlen)) + fail ("poly1305, encrypt mismatch entry %d, (byte-buf)\n", i); + + err = gcry_cipher_gettag (hde, tag, 16); + if (err) + { + fail ("poly1305, gcry_cipher_gettag(%d) (byte-buf) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (memcmp (tv[i].tag, tag, 16)) + fail ("poly1305, encrypt tag mismatch entry %d, (byte-buf)\n", i); + + for (byteNum = 0; byteNum < tv[i].inlen; ++byteNum) + { + err = gcry_cipher_decrypt (hdd, out+byteNum, 1, NULL, 0); + if (err) + { + fail ("poly1305, gcry_cipher_decrypt (%d) (byte-buf) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + } + + if (memcmp (tv[i].plaintext, out, tv[i].inlen)) + fail ("poly1305, decrypt mismatch entry %d\n", i); + + err = gcry_cipher_checktag (hdd, tag, 16); + if (err) + { + fail ("poly1305, gcry_cipher_checktag(%d) (byte-buf) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + } + if (verbose) + fprintf (stderr, " Completed POLY1305 checks.\n"); +} + + +static void +check_poly1305_cipher (void) +{ + /* Large buffers, no splitting. */ + _check_poly1305_cipher(0xffffffff); + /* Split input to one byte buffers. */ + _check_poly1305_cipher(1); + /* Split input to 7 byte buffers. */ + _check_poly1305_cipher(7); + /* Split input to 16 byte buffers. */ + _check_poly1305_cipher(16); +} + + +static void check_ccm_cipher (void) { #ifdef HAVE_U64_TYPEDEF @@ -4019,6 +4333,10 @@ check_ciphers (void) gcry_cipher_algo_name (algos2[i])); check_one_cipher (algos2[i], GCRY_CIPHER_MODE_STREAM, 0); + if (algos2[i] == GCRY_CIPHER_CHACHA20 || + algos2[i] == GCRY_CIPHER_SALSA20 || + algos2[i] == GCRY_CIPHER_SALSA20R12) + check_one_cipher (algos2[i], GCRY_CIPHER_MODE_POLY1305, 0); } /* we have now run all cipher's selftests */ @@ -4042,6 +4360,7 @@ check_cipher_modes(void) check_ofb_cipher (); check_ccm_cipher (); check_gcm_cipher (); + check_poly1305_cipher (); check_stream_cipher (); check_stream_cipher_large_block (); diff --git a/tests/bench-slope.c b/tests/bench-slope.c index a911ef8..7bf587f 100644 --- a/tests/bench-slope.c +++ b/tests/bench-slope.c @@ -907,15 +907,14 @@ static struct bench_ops ccm_authenticate_ops = { static void -bench_gcm_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) +bench_aead_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen, + const char *nonce, size_t noncelen) { gcry_cipher_hd_t hd = obj->priv; int err; char tag[16]; - char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, - 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, }; - gcry_cipher_setiv (hd, nonce, sizeof (nonce)); + gcry_cipher_setiv (hd, nonce, noncelen); err = gcry_cipher_encrypt (hd, buf, buflen, buf, buflen); if (err) @@ -937,15 +936,14 @@ bench_gcm_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) } static void -bench_gcm_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) +bench_aead_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen, + const char *nonce, size_t noncelen) { gcry_cipher_hd_t hd = obj->priv; int err; char tag[16] = { 0, }; - char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, - 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, }; - gcry_cipher_setiv (hd, nonce, sizeof (nonce)); + gcry_cipher_setiv (hd, nonce, noncelen); err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen); if (err) @@ -969,17 +967,16 @@ bench_gcm_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) } static void -bench_gcm_authenticate_do_bench (struct bench_obj *obj, void *buf, - size_t buflen) +bench_aead_authenticate_do_bench (struct bench_obj *obj, void *buf, + size_t buflen, const char *nonce, + size_t noncelen) { gcry_cipher_hd_t hd = obj->priv; int err; char tag[16] = { 0, }; - char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, - 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, }; char data = 0xff; - gcry_cipher_setiv (hd, nonce, sizeof (nonce)); + gcry_cipher_setiv (hd, nonce, noncelen); err = gcry_cipher_authenticate (hd, buf, buflen); if (err) @@ -1009,6 +1006,34 @@ bench_gcm_authenticate_do_bench (struct bench_obj *obj, void *buf, } } + +static void +bench_gcm_encrypt_do_bench (struct bench_obj *obj, void *buf, + size_t buflen) +{ + char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, + 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, }; + bench_aead_encrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); +} + +static void +bench_gcm_decrypt_do_bench (struct bench_obj *obj, void *buf, + size_t buflen) +{ + char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, + 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, }; + bench_aead_decrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); +} + +static void +bench_gcm_authenticate_do_bench (struct bench_obj *obj, void *buf, + size_t buflen) +{ + char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, + 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, }; + bench_aead_authenticate_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); +} + static struct bench_ops gcm_encrypt_ops = { &bench_encrypt_init, &bench_encrypt_free, @@ -1028,6 +1053,49 @@ static struct bench_ops gcm_authenticate_ops = { }; +static void +bench_poly1305_encrypt_do_bench (struct bench_obj *obj, void *buf, + size_t buflen) +{ + char nonce[8] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad }; + bench_aead_encrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); +} + +static void +bench_poly1305_decrypt_do_bench (struct bench_obj *obj, void *buf, + size_t buflen) +{ + char nonce[8] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad }; + bench_aead_decrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); +} + +static void +bench_poly1305_authenticate_do_bench (struct bench_obj *obj, void *buf, + size_t buflen) +{ + char nonce[8] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad }; + bench_aead_authenticate_do_bench (obj, buf, buflen, nonce, sizeof(nonce)); +} + +static struct bench_ops poly1305_encrypt_ops = { + &bench_encrypt_init, + &bench_encrypt_free, + &bench_poly1305_encrypt_do_bench +}; + +static struct bench_ops poly1305_decrypt_ops = { + &bench_encrypt_init, + &bench_encrypt_free, + &bench_poly1305_decrypt_do_bench +}; + +static struct bench_ops poly1305_authenticate_ops = { + &bench_encrypt_init, + &bench_encrypt_free, + &bench_poly1305_authenticate_do_bench +}; + + static struct bench_cipher_mode cipher_modes[] = { {GCRY_CIPHER_MODE_ECB, "ECB enc", &encrypt_ops}, {GCRY_CIPHER_MODE_ECB, "ECB dec", &decrypt_ops}, @@ -1047,6 +1115,9 @@ static struct bench_cipher_mode cipher_modes[] = { {GCRY_CIPHER_MODE_GCM, "GCM enc", &gcm_encrypt_ops}, {GCRY_CIPHER_MODE_GCM, "GCM dec", &gcm_decrypt_ops}, {GCRY_CIPHER_MODE_GCM, "GCM auth", &gcm_authenticate_ops}, + {GCRY_CIPHER_MODE_POLY1305, "POLY1305 enc", &poly1305_encrypt_ops}, + {GCRY_CIPHER_MODE_POLY1305, "POLY1305 dec", &poly1305_decrypt_ops}, + {GCRY_CIPHER_MODE_POLY1305, "POLY1305 auth", &poly1305_authenticate_ops}, {0}, }; @@ -1066,8 +1137,9 @@ cipher_bench_one (int algo, struct bench_cipher_mode *pmode) if (!blklen) return; - /* Stream cipher? Only test with ECB. */ - if (blklen == 1 && mode.mode != GCRY_CIPHER_MODE_ECB) + /* Stream cipher? Only test with "ECB" and POLY1305. */ + if (blklen == 1 && (mode.mode != GCRY_CIPHER_MODE_ECB && + mode.mode != GCRY_CIPHER_MODE_POLY1305)) return; if (blklen == 1 && mode.mode == GCRY_CIPHER_MODE_ECB) { @@ -1075,6 +1147,12 @@ cipher_bench_one (int algo, struct bench_cipher_mode *pmode) mode.name = mode.ops == &encrypt_ops ? "STREAM enc" : "STREAM dec"; } + /* Poly1305 has restrictions for cipher algorithm */ + if (mode.mode == GCRY_CIPHER_MODE_POLY1305 && + (algo != GCRY_CIPHER_SALSA20 && algo != GCRY_CIPHER_SALSA20R12 && + algo != GCRY_CIPHER_CHACHA20)) + return; + /* CCM has restrictions for block-size */ if (mode.mode == GCRY_CIPHER_MODE_CCM && blklen != GCRY_CCM_BLOCK_LEN) return; commit 73b3b75c2221a6e3bed4117e0a206a1193acd2ed Author: Jussi Kivilinna Date: Sun May 11 12:00:19 2014 +0300 Add Poly1305-AES (-Camellia, etc) MACs * cipher/mac-internal.h (_gcry_mac_type_spec_poly1305_aes) (_gcry_mac_type_spec_poly1305_camellia) (_gcry_mac_type_spec_poly1305_twofish) (_gcry_mac_type_spec_poly1305_serpent) (_gcry_mac_type_spec_poly1305_seed): New. * cipher/mac-poly1305.c (poly1305mac_context_s): Add 'hd' and 'nonce_set'. (poly1305mac_open, poly1305mac_close, poly1305mac_setkey): Add handling for Poly1305-*** MACs. (poly1305mac_prepare_key, poly1305mac_setiv): New. (poly1305mac_reset, poly1305mac_write, poly1305mac_read): Add handling for 'nonce_set'. (poly1305mac_ops): Add 'poly1305mac_setiv'. (_gcry_mac_type_spec_poly1305_aes) (_gcry_mac_type_spec_poly1305_camellia) (_gcry_mac_type_spec_poly1305_twofish) (_gcry_mac_type_spec_poly1305_serpent) (_gcry_mac_type_spec_poly1305_seed): New. * cipher/mac.c (mac_list): Add Poly1305-AES, Poly1305-Twofish, Poly1305-Serpent, Poly1305-SEED and Poly1305-Camellia. * src/gcrypt.h.in: Add 'GCRY_MAC_POLY1305_AES', 'GCRY_MAC_POLY1305_CAMELLIA', 'GCRY_MAC_POLY1305_TWOFISH', 'GCRY_MAC_POLY1305_SERPENT' and 'GCRY_MAC_POLY1305_SEED'. * tests/basic.c (check_mac): Add Poly1305-AES test vectors. * tests/bench-slope.c (bench_mac_init): Set IV for Poly1305-*** MACs. * tests/bench-slope.c (mac_bench): Set IV for Poly1305-*** MACs. -- Patch adds Bernstein's Poly1305-AES message authentication code to libgcrypt and other variants of Poly1305-<128-bit block cipher>. Signed-off-by: Jussi Kivilinna diff --git a/cipher/mac-internal.h b/cipher/mac-internal.h index 81b6185..f65a8ae 100644 --- a/cipher/mac-internal.h +++ b/cipher/mac-internal.h @@ -217,3 +217,18 @@ extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_camellia; * The Poly1305 MAC algorithm specifications (mac-poly1305.c). */ extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac; +#if USE_AES +extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_aes; +#endif +#if USE_CAMELLIA +extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_camellia; +#endif +#if USE_TWOFISH +extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_twofish; +#endif +#if USE_SERPENT +extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_serpent; +#endif +#if USE_SEED +extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_seed; +#endif diff --git a/cipher/mac-poly1305.c b/cipher/mac-poly1305.c index e265b64..76b369a 100644 --- a/cipher/mac-poly1305.c +++ b/cipher/mac-poly1305.c @@ -30,8 +30,10 @@ struct poly1305mac_context_s { poly1305_context_t ctx; + gcry_cipher_hd_t hd; struct { unsigned int key_set:1; + unsigned int nonce_set:1; unsigned int tag:1; } marks; byte tag[POLY1305_TAGLEN]; @@ -44,6 +46,9 @@ poly1305mac_open (gcry_mac_hd_t h) { struct poly1305mac_context_s *mac_ctx; int secure = (h->magic == CTX_MAGIC_SECURE); + unsigned int flags = (secure ? GCRY_CIPHER_SECURE : 0); + gcry_err_code_t err; + int cipher_algo; if (secure) mac_ctx = xtrycalloc_secure (1, sizeof(*mac_ctx)); @@ -55,14 +60,71 @@ poly1305mac_open (gcry_mac_hd_t h) h->u.poly1305mac.ctx = mac_ctx; + switch (h->spec->algo) + { + default: + /* already checked. */ + case GCRY_MAC_POLY1305: + /* plain Poly1305. */ + cipher_algo = -1; + return 0; + case GCRY_MAC_POLY1305_AES: + cipher_algo = GCRY_CIPHER_AES; + break; + case GCRY_MAC_POLY1305_CAMELLIA: + cipher_algo = GCRY_CIPHER_CAMELLIA128; + break; + case GCRY_MAC_POLY1305_TWOFISH: + cipher_algo = GCRY_CIPHER_TWOFISH; + break; + case GCRY_MAC_POLY1305_SERPENT: + cipher_algo = GCRY_CIPHER_SERPENT128; + break; + case GCRY_MAC_POLY1305_SEED: + cipher_algo = GCRY_CIPHER_SEED; + break; + } + + err = _gcry_cipher_open_internal (&mac_ctx->hd, cipher_algo, + GCRY_CIPHER_MODE_ECB, flags); + if (err) + goto err_free; + return 0; + +err_free: + xfree(h->u.poly1305mac.ctx); + return err; } static void poly1305mac_close (gcry_mac_hd_t h) { - xfree(h->u.poly1305mac.ctx); + struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; + + if (h->spec->algo != GCRY_MAC_POLY1305) + _gcry_cipher_close (mac_ctx->hd); + + xfree(mac_ctx); +} + + +static gcry_err_code_t +poly1305mac_prepare_key (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) +{ + struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; + size_t block_keylen = keylen - 16; + + /* Need at least 16 + 1 byte key. */ + if (keylen <= 16) + return GPG_ERR_INV_KEYLEN; + + /* For Poly1305-AES, first part of key is passed to Poly1305 as is. */ + memcpy (mac_ctx->key, key + block_keylen, 16); + + /* Remaining part is used as key for the block cipher. */ + return _gcry_cipher_setkey (mac_ctx->hd, key, block_keylen); } @@ -77,22 +139,74 @@ poly1305mac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) memset(&mac_ctx->key, 0, sizeof(mac_ctx->key)); mac_ctx->marks.key_set = 0; + mac_ctx->marks.nonce_set = 0; mac_ctx->marks.tag = 0; - if (keylen != POLY1305_KEYLEN) - return GPG_ERR_INV_KEYLEN; - - memcpy(mac_ctx->key, key, POLY1305_KEYLEN); + if (h->spec->algo != GCRY_MAC_POLY1305) + { + err = poly1305mac_prepare_key (h, key, keylen); + if (err) + return err; - err = _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN); - if (err) + /* Poly1305-AES/etc also need nonce. */ + mac_ctx->marks.key_set = 1; + mac_ctx->marks.nonce_set = 0; + } + else { - memset(&mac_ctx->key, 0, sizeof(mac_ctx->key)); - return err; + /* For plain Poly1305, key is the nonce and setup is complete now. */ + + if (keylen != POLY1305_KEYLEN) + return GPG_ERR_INV_KEYLEN; + + memcpy (mac_ctx->key, key, keylen); + + err = _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN); + if (err) + { + memset(&mac_ctx->key, 0, sizeof(mac_ctx->key)); + return err; + } + + mac_ctx->marks.key_set = 1; + mac_ctx->marks.nonce_set = 1; } - mac_ctx->marks.key_set = 1; + return 0; +} + + +static gcry_err_code_t +poly1305mac_setiv (gcry_mac_hd_t h, const unsigned char *iv, size_t ivlen) +{ + struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; + gcry_err_code_t err; + + if (h->spec->algo == GCRY_MAC_POLY1305) + return GPG_ERR_INV_ARG; + + if (ivlen != 16) + return GPG_ERR_INV_ARG; + if (!mac_ctx->marks.key_set) + return 0; + + memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); + memset(&mac_ctx->tag, 0, sizeof(mac_ctx->tag)); + mac_ctx->marks.nonce_set = 0; + mac_ctx->marks.tag = 0; + + /* Prepare second part of the poly1305 key. */ + + err = _gcry_cipher_encrypt (mac_ctx->hd, mac_ctx->key + 16, 16, iv, 16); + if (err) + return err; + + err = _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN); + if (err) + return err; + + mac_ctx->marks.nonce_set = 1; return 0; } @@ -102,13 +216,14 @@ poly1305mac_reset (gcry_mac_hd_t h) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; - if (!mac_ctx->marks.key_set) + if (!mac_ctx->marks.key_set || !mac_ctx->marks.nonce_set) return GPG_ERR_INV_STATE; memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); memset(&mac_ctx->tag, 0, sizeof(mac_ctx->tag)); mac_ctx->marks.key_set = 1; + mac_ctx->marks.nonce_set = 1; mac_ctx->marks.tag = 0; return _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN); @@ -120,7 +235,8 @@ poly1305mac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; - if (!mac_ctx->marks.key_set || mac_ctx->marks.tag) + if (!mac_ctx->marks.key_set || !mac_ctx->marks.nonce_set || + mac_ctx->marks.tag) return GPG_ERR_INV_STATE; _gcry_poly1305_update (&mac_ctx->ctx, buf, buflen); @@ -133,7 +249,7 @@ poly1305mac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t *outlen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; - if (!mac_ctx->marks.key_set) + if (!mac_ctx->marks.key_set || !mac_ctx->marks.nonce_set) return GPG_ERR_INV_STATE; if (!mac_ctx->marks.tag) @@ -197,7 +313,7 @@ static gcry_mac_spec_ops_t poly1305mac_ops = { poly1305mac_open, poly1305mac_close, poly1305mac_setkey, - NULL, + poly1305mac_setiv, poly1305mac_reset, poly1305mac_write, poly1305mac_read, @@ -211,3 +327,33 @@ gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac = { GCRY_MAC_POLY1305, {0, 0}, "POLY1305", &poly1305mac_ops }; +#if USE_AES +gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_aes = { + GCRY_MAC_POLY1305_AES, {0, 0}, "POLY1305_AES", + &poly1305mac_ops +}; +#endif +#if USE_CAMELLIA +gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_camellia = { + GCRY_MAC_POLY1305_CAMELLIA, {0, 0}, "POLY1305_CAMELLIA", + &poly1305mac_ops +}; +#endif +#if USE_TWOFISH +gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_twofish = { + GCRY_MAC_POLY1305_TWOFISH, {0, 0}, "POLY1305_TWOFISH", + &poly1305mac_ops +}; +#endif +#if USE_SERPENT +gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_serpent = { + GCRY_MAC_POLY1305_SERPENT, {0, 0}, "POLY1305_SERPENT", + &poly1305mac_ops +}; +#endif +#if USE_SEED +gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_seed = { + GCRY_MAC_POLY1305_SEED, {0, 0}, "POLY1305_SEED", + &poly1305mac_ops +}; +#endif diff --git a/cipher/mac.c b/cipher/mac.c index e583369..30117b9 100644 --- a/cipher/mac.c +++ b/cipher/mac.c @@ -75,14 +75,17 @@ static gcry_mac_spec_t *mac_list[] = { #if USE_AES &_gcry_mac_type_spec_cmac_aes, &_gcry_mac_type_spec_gmac_aes, + &_gcry_mac_type_spec_poly1305mac_aes, #endif #if USE_TWOFISH &_gcry_mac_type_spec_cmac_twofish, &_gcry_mac_type_spec_gmac_twofish, + &_gcry_mac_type_spec_poly1305mac_twofish, #endif #if USE_SERPENT &_gcry_mac_type_spec_cmac_serpent, &_gcry_mac_type_spec_gmac_serpent, + &_gcry_mac_type_spec_poly1305mac_serpent, #endif #if USE_RFC2268 &_gcry_mac_type_spec_cmac_rfc2268, @@ -90,10 +93,12 @@ static gcry_mac_spec_t *mac_list[] = { #if USE_SEED &_gcry_mac_type_spec_cmac_seed, &_gcry_mac_type_spec_gmac_seed, + &_gcry_mac_type_spec_poly1305mac_seed, #endif #if USE_CAMELLIA &_gcry_mac_type_spec_cmac_camellia, &_gcry_mac_type_spec_gmac_camellia, + &_gcry_mac_type_spec_poly1305mac_camellia, #endif #ifdef USE_IDEA &_gcry_mac_type_spec_cmac_idea, diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 8648e96..3145020 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -1343,7 +1343,12 @@ enum gcry_mac_algos GCRY_MAC_GMAC_SERPENT = 404, GCRY_MAC_GMAC_SEED = 405, - GCRY_MAC_POLY1305 = 501 + GCRY_MAC_POLY1305 = 501, + GCRY_MAC_POLY1305_AES = 502, + GCRY_MAC_POLY1305_CAMELLIA = 503, + GCRY_MAC_POLY1305_TWOFISH = 504, + GCRY_MAC_POLY1305_SERPENT = 505, + GCRY_MAC_POLY1305_SEED = 506 }; /* Flags used with the open function. */ diff --git a/tests/basic.c b/tests/basic.c index cc0f4c1..de10617 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -5596,6 +5596,39 @@ check_mac (void) "\x12\x97\x6a\x08\xc4\x42\x6d\x0c\xe8\xa8\x24\x07\xc4\xf4\x82\x07" "\x80\xf8\xc2\x0a\xa7\x12\x02\xd1\xe2\x91\x79\xcb\xcb\x55\x5a\x57", "\x51\x54\xad\x0d\x2c\xb2\x6e\x01\x27\x4f\xc5\x11\x48\x49\x1f\x1b" }, + /* from http://cr.yp.to/mac/poly1305-20050329.pdf */ + { GCRY_MAC_POLY1305_AES, + "\xf3\xf6", + "\xec\x07\x4c\x83\x55\x80\x74\x17\x01\x42\x5b\x62\x32\x35\xad\xd6" + "\x85\x1f\xc4\x0c\x34\x67\xac\x0b\xe0\x5c\xc2\x04\x04\xf3\xf7\x00", + "\xf4\xc6\x33\xc3\x04\x4f\xc1\x45\xf8\x4f\x33\x5c\xb8\x19\x53\xde", + "\xfb\x44\x73\x50\xc4\xe8\x68\xc5\x2a\xc3\x27\x5c\xf9\xd4\x32\x7e", + 0, 32 }, + { GCRY_MAC_POLY1305_AES, + "", + "\x75\xde\xaa\x25\xc0\x9f\x20\x8e\x1d\xc4\xce\x6b\x5c\xad\x3f\xbf" + "\xa0\xf3\x08\x00\x00\xf4\x64\x00\xd0\xc7\xe9\x07\x6c\x83\x44\x03", + "\xdd\x3f\xab\x22\x51\xf1\x1a\xc7\x59\xf0\x88\x71\x29\xcc\x2e\xe7", + "\x61\xee\x09\x21\x8d\x29\xb0\xaa\xed\x7e\x15\x4a\x2c\x55\x09\xcc", + 0, 32 }, + { GCRY_MAC_POLY1305_AES, + "\x66\x3c\xea\x19\x0f\xfb\x83\xd8\x95\x93\xf3\xf4\x76\xb6\xbc\x24" + "\xd7\xe6\x79\x10\x7e\xa2\x6a\xdb\x8c\xaf\x66\x52\xd0\x65\x61\x36", + "\x6a\xcb\x5f\x61\xa7\x17\x6d\xd3\x20\xc5\xc1\xeb\x2e\xdc\xdc\x74" + "\x48\x44\x3d\x0b\xb0\xd2\x11\x09\xc8\x9a\x10\x0b\x5c\xe2\xc2\x08", + "\x0e\xe1\xc1\x6b\xb7\x3f\x0f\x4f\xd1\x98\x81\x75\x3c\x01\xcd\xbe", + "\xae\x21\x2a\x55\x39\x97\x29\x59\x5d\xea\x45\x8b\xc6\x21\xff\x0e", + 0, 32 }, + { GCRY_MAC_POLY1305_AES, + "\xab\x08\x12\x72\x4a\x7f\x1e\x34\x27\x42\xcb\xed\x37\x4d\x94\xd1" + "\x36\xc6\xb8\x79\x5d\x45\xb3\x81\x98\x30\xf2\xc0\x44\x91\xfa\xf0" + "\x99\x0c\x62\xe4\x8b\x80\x18\xb2\xc3\xe4\xa0\xfa\x31\x34\xcb\x67" + "\xfa\x83\xe1\x58\xc9\x94\xd9\x61\xc4\xcb\x21\x09\x5c\x1b\xf9", + "\xe1\xa5\x66\x8a\x4d\x5b\x66\xa5\xf6\x8c\xc5\x42\x4e\xd5\x98\x2d" + "\x12\x97\x6a\x08\xc4\x42\x6d\x0c\xe8\xa8\x24\x07\xc4\xf4\x82\x07", + "\x51\x54\xad\x0d\x2c\xb2\x6e\x01\x27\x4f\xc5\x11\x48\x49\x1f\x1b", + "\x9a\xe8\x31\xe7\x43\x97\x8d\x3a\x23\x52\x7c\x71\x28\x14\x9e\x3a", + 0, 32 }, { 0 }, }; int i; diff --git a/tests/bench-slope.c b/tests/bench-slope.c index 3d8ae37..a911ef8 100644 --- a/tests/bench-slope.c +++ b/tests/bench-slope.c @@ -1316,6 +1316,19 @@ bench_mac_init (struct bench_obj *obj) exit (1); } + switch (mode->algo) + { + default: + break; + case GCRY_MAC_POLY1305_AES: + case GCRY_MAC_POLY1305_CAMELLIA: + case GCRY_MAC_POLY1305_TWOFISH: + case GCRY_MAC_POLY1305_SERPENT: + case GCRY_MAC_POLY1305_SEED: + gcry_mac_setiv (hd, key, 16); + break; + } + obj->priv = hd; return 0; diff --git a/tests/benchmark.c b/tests/benchmark.c index 9fd716d..042e721 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -509,6 +509,18 @@ mac_bench ( const char *algoname ) for (i=0; i < bufsize; i++) buf[i] = i; + if (algo >= GCRY_MAC_POLY1305_AES && algo <= GCRY_MAC_POLY1305_SEED) + { + static const char iv[16] = { 1, 2, 3, 4, }; + err = gcry_mac_setiv(hd, iv, sizeof(iv)); + if (err) + { + fprintf (stderr, PGM ": error setting nonce for mac algorithm `%s': %s\n", + algoname, gpg_strerror (err)); + exit (1); + } + } + printf ("%-20s", gcry_mac_algo_name (algo)); start_timer (); commit b8794fed68ebe7567f4617141f0996ad290d9120 Author: Jussi Kivilinna Date: Sun May 11 12:00:19 2014 +0300 Add Poly1305 MAC * cipher/Makefile.am: Add 'mac-poly1305.c', 'poly1305.c' and 'poly1305-internal.h'. * cipher/mac-internal.h (poly1305mac_context_s): New. (gcry_mac_handle): Add 'u.poly1305mac'. (_gcry_mac_type_spec_poly1305mac): New. * cipher/mac-poly1305.c: New. * cipher/mac.c (mac_list): Add Poly1305. * cipher/poly1305-internal.h: New. * cipher/poly1305.c: New. * src/gcrypt.h.in: Add 'GCRY_MAC_POLY1305'. * tests/basic.c (check_mac): Add Poly1035 test vectors; Allow overriding lengths of data and key buffers. * tests/bench-slope.c (mac_bench): Increase max algo number from 500 to 600. * tests/benchmark.c (mac_bench): Ditto. -- Patch adds Bernstein's Poly1305 message authentication code to libgcrypt. Implementation is based on Andrew Moon's public domain implementation from: https://github.com/floodyberry/poly1305-opt The algorithm added by this patch is the plain Poly1305 without AES and takes 32-bit key that must not be reused. Signed-off-by: Jussi Kivilinna diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 26d13d2..a8b86e6 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -45,7 +45,8 @@ cipher-selftest.c cipher-selftest.h \ pubkey.c pubkey-internal.h pubkey-util.c \ md.c \ mac.c mac-internal.h \ -mac-hmac.c mac-cmac.c mac-gmac.c \ +mac-hmac.c mac-cmac.c mac-gmac.c mac-poly1305.c \ +poly1305.c poly1305-internal.h \ kdf.c kdf-internal.h \ hmac-tests.c \ bithelp.h \ diff --git a/cipher/mac-internal.h b/cipher/mac-internal.h index 9895a54..81b6185 100644 --- a/cipher/mac-internal.h +++ b/cipher/mac-internal.h @@ -17,9 +17,17 @@ * License along with this program; if not, see . */ +#include + +#include "g10lib.h" + + /* The data object used to hold a handle to an encryption object. */ struct gcry_mac_handle; +/* The data object used to hold poly1305-mac context. */ +struct poly1305mac_context_s; + /* * @@ -84,7 +92,6 @@ typedef struct gcry_mac_spec } gcry_mac_spec_t; - /* The handle structure. */ struct gcry_mac_handle { @@ -106,6 +113,9 @@ struct gcry_mac_handle gcry_cipher_hd_t ctx; int cipher_algo; } gmac; + struct { + struct poly1305mac_context_s *ctx; + } poly1305mac; } u; }; @@ -202,3 +212,8 @@ extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_seed; #if USE_CAMELLIA extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_camellia; #endif + +/* + * The Poly1305 MAC algorithm specifications (mac-poly1305.c). + */ +extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac; diff --git a/cipher/mac-poly1305.c b/cipher/mac-poly1305.c new file mode 100644 index 0000000..e265b64 --- /dev/null +++ b/cipher/mac-poly1305.c @@ -0,0 +1,213 @@ +/* mac-poly1305.c - Poly1305 based MACs + * Copyright (C) 2014 Jussi Kivilinna + * + * 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, see . + */ + +#include +#include +#include +#include +#include + +#include "g10lib.h" +#include "mac-internal.h" +#include "poly1305-internal.h" + + +struct poly1305mac_context_s { + poly1305_context_t ctx; + struct { + unsigned int key_set:1; + unsigned int tag:1; + } marks; + byte tag[POLY1305_TAGLEN]; + byte key[POLY1305_KEYLEN]; +}; + + +static gcry_err_code_t +poly1305mac_open (gcry_mac_hd_t h) +{ + struct poly1305mac_context_s *mac_ctx; + int secure = (h->magic == CTX_MAGIC_SECURE); + + if (secure) + mac_ctx = xtrycalloc_secure (1, sizeof(*mac_ctx)); + else + mac_ctx = xtrycalloc (1, sizeof(*mac_ctx)); + + if (!mac_ctx) + return gpg_err_code_from_syserror (); + + h->u.poly1305mac.ctx = mac_ctx; + + return 0; +} + + +static void +poly1305mac_close (gcry_mac_hd_t h) +{ + xfree(h->u.poly1305mac.ctx); +} + + +static gcry_err_code_t +poly1305mac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) +{ + struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; + gcry_err_code_t err; + + memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); + memset(&mac_ctx->tag, 0, sizeof(mac_ctx->tag)); + memset(&mac_ctx->key, 0, sizeof(mac_ctx->key)); + + mac_ctx->marks.key_set = 0; + mac_ctx->marks.tag = 0; + + if (keylen != POLY1305_KEYLEN) + return GPG_ERR_INV_KEYLEN; + + memcpy(mac_ctx->key, key, POLY1305_KEYLEN); + + err = _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN); + if (err) + { + memset(&mac_ctx->key, 0, sizeof(mac_ctx->key)); + return err; + } + + mac_ctx->marks.key_set = 1; + + return 0; +} + + +static gcry_err_code_t +poly1305mac_reset (gcry_mac_hd_t h) +{ + struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; + + if (!mac_ctx->marks.key_set) + return GPG_ERR_INV_STATE; + + memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); + memset(&mac_ctx->tag, 0, sizeof(mac_ctx->tag)); + + mac_ctx->marks.key_set = 1; + mac_ctx->marks.tag = 0; + + return _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN); +} + + +static gcry_err_code_t +poly1305mac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) +{ + struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; + + if (!mac_ctx->marks.key_set || mac_ctx->marks.tag) + return GPG_ERR_INV_STATE; + + _gcry_poly1305_update (&mac_ctx->ctx, buf, buflen); + return 0; +} + + +static gcry_err_code_t +poly1305mac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t *outlen) +{ + struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; + + if (!mac_ctx->marks.key_set) + return GPG_ERR_INV_STATE; + + if (!mac_ctx->marks.tag) + { + _gcry_poly1305_finish(&mac_ctx->ctx, mac_ctx->tag); + + memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); + mac_ctx->marks.tag = 1; + } + + if (*outlen <= POLY1305_TAGLEN) + buf_cpy (outbuf, mac_ctx->tag, *outlen); + else + { + buf_cpy (outbuf, mac_ctx->tag, POLY1305_TAGLEN); + *outlen = POLY1305_TAGLEN; + } + + return 0; +} + + +static gcry_err_code_t +poly1305mac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) +{ + struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; + gcry_err_code_t err; + size_t outlen = 0; + + /* Check and finalize tag. */ + err = poly1305mac_read(h, NULL, &outlen); + if (err) + return err; + + if (buflen > POLY1305_TAGLEN) + return GPG_ERR_INV_LENGTH; + + return buf_eq_const (buf, mac_ctx->tag, buflen) ? 0 : GPG_ERR_CHECKSUM; +} + + +static unsigned int +poly1305mac_get_maclen (int algo) +{ + (void)algo; + + return POLY1305_TAGLEN; +} + + +static unsigned int +poly1305mac_get_keylen (int algo) +{ + (void)algo; + + return POLY1305_KEYLEN; +} + + +static gcry_mac_spec_ops_t poly1305mac_ops = { + poly1305mac_open, + poly1305mac_close, + poly1305mac_setkey, + NULL, + poly1305mac_reset, + poly1305mac_write, + poly1305mac_read, + poly1305mac_verify, + poly1305mac_get_maclen, + poly1305mac_get_keylen +}; + + +gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac = { + GCRY_MAC_POLY1305, {0, 0}, "POLY1305", + &poly1305mac_ops +}; diff --git a/cipher/mac.c b/cipher/mac.c index 7805467..e583369 100644 --- a/cipher/mac.c +++ b/cipher/mac.c @@ -101,6 +101,7 @@ static gcry_mac_spec_t *mac_list[] = { #if USE_GOST28147 &_gcry_mac_type_spec_cmac_gost28147, #endif + &_gcry_mac_type_spec_poly1305mac, NULL, }; diff --git a/cipher/poly1305-internal.h b/cipher/poly1305-internal.h new file mode 100644 index 0000000..d2c6b5c --- /dev/null +++ b/cipher/poly1305-internal.h @@ -0,0 +1,93 @@ +/* poly1305-internal.h - Poly1305 internals + * Copyright (C) 2014 Jussi Kivilinna + * + * 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, see . + */ + +#ifndef G10_POLY1305_INTERNAL_H +#define G10_POLY1305_INTERNAL_H + +#include +#include +#include +#include +#include "types.h" +#include "g10lib.h" +#include "cipher.h" +#include "bufhelp.h" + + +#define POLY1305_TAGLEN 16 +#define POLY1305_KEYLEN 32 + + +/* Block-size used in default implementation. */ +#define POLY1305_REF_BLOCKSIZE 16 + +/* State size of default implementation. */ +#define POLY1305_REF_STATESIZE 64 + +/* State alignment for default implementation. */ +#define POLY1305_REF_ALIGNMENT sizeof(void *) + + +/* Largest block-size used in any implementation (optimized implementations + * might use block-size multiple of 16). */ +#define POLY1305_LARGEST_BLOCKSIZE POLY1305_REF_BLOCKSIZE + +/* Largest state-size used in any implementation. */ +#define POLY1305_LARGEST_STATESIZE POLY1305_REF_STATESIZE + +/* Minimum alignment for state pointer passed to implementations. */ +#define POLY1305_STATE_ALIGNMENT POLY1305_REF_ALIGNMENT + + +typedef struct poly1305_key_s +{ + byte b[POLY1305_KEYLEN]; +} poly1305_key_t; + + +typedef struct poly1305_ops_s +{ + size_t block_size; + void (*init_ext) (void *ctx, const poly1305_key_t * key); + unsigned int (*blocks) (void *ctx, const byte * m, size_t bytes); + unsigned int (*finish_ext) (void *ctx, const byte * m, size_t remaining, + byte mac[POLY1305_TAGLEN]); +} poly1305_ops_t; + + +typedef struct poly1305_context_s +{ + byte state[POLY1305_LARGEST_STATESIZE + POLY1305_STATE_ALIGNMENT]; + byte buffer[POLY1305_LARGEST_BLOCKSIZE]; + const poly1305_ops_t *ops; + unsigned int leftover; +} poly1305_context_t; + + +gcry_err_code_t _gcry_poly1305_init (poly1305_context_t * ctx, const byte * key, + size_t keylen); + +void _gcry_poly1305_finish (poly1305_context_t * ctx, + byte mac[POLY1305_TAGLEN]); + +void _gcry_poly1305_update (poly1305_context_t * ctx, const byte * buf, + size_t buflen); + + +#endif /* G10_POLY1305_INTERNAL_H */ diff --git a/cipher/poly1305.c b/cipher/poly1305.c new file mode 100644 index 0000000..472ae42 --- /dev/null +++ b/cipher/poly1305.c @@ -0,0 +1,766 @@ +/* poly1305.c - Poly1305 internals and generic implementation + * Copyright (C) 2014 Jussi Kivilinna + * + * 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, see . + */ + +/* The code is based on public-domain Poly1305 implementation by + * Andrew Moon at + * https://github.com/floodyberry/poly1305-opt + */ + +#include +#include +#include +#include + +#include "types.h" +#include "g10lib.h" +#include "cipher.h" +#include "bufhelp.h" +#include "poly1305-internal.h" + + +static const char *selftest (void); + + + +#ifdef HAVE_U64_TYPEDEF + +/* Reference unoptimized poly1305 implementation using 32 bit * 32 bit = 64 bit + * multiplication and 64 bit addition. + */ + +typedef struct poly1305_state_ref32_s +{ + u32 r[5]; + u32 h[5]; + u32 pad[4]; + byte final; +} poly1305_state_ref32_t; + + +static void +poly1305_init_ext_ref32 (void *state, const poly1305_key_t * key) +{ + poly1305_state_ref32_t *st = (poly1305_state_ref32_t *) state; + + gcry_assert (sizeof (*st) + POLY1305_STATE_ALIGNMENT <= + sizeof (((poly1305_context_t *) 0)->state)); + + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ + st->r[0] = (buf_get_le32 (&key->b[0])) & 0x3ffffff; + st->r[1] = (buf_get_le32 (&key->b[3]) >> 2) & 0x3ffff03; + st->r[2] = (buf_get_le32 (&key->b[6]) >> 4) & 0x3ffc0ff; + st->r[3] = (buf_get_le32 (&key->b[9]) >> 6) & 0x3f03fff; + st->r[4] = (buf_get_le32 (&key->b[12]) >> 8) & 0x00fffff; + + /* h = 0 */ + st->h[0] = 0; + st->h[1] = 0; + st->h[2] = 0; + st->h[3] = 0; + st->h[4] = 0; + + /* save pad for later */ + st->pad[0] = buf_get_le32 (&key->b[16]); + st->pad[1] = buf_get_le32 (&key->b[20]); + st->pad[2] = buf_get_le32 (&key->b[24]); + st->pad[3] = buf_get_le32 (&key->b[28]); + + st->final = 0; +} + + +static unsigned int +poly1305_blocks_ref32 (void *state, const byte * m, size_t bytes) +{ + poly1305_state_ref32_t *st = (poly1305_state_ref32_t *) state; + const u32 hibit = (st->final) ? 0 : (1 << 24); /* 1 << 128 */ + u32 r0, r1, r2, r3, r4; + u32 s1, s2, s3, s4; + u32 h0, h1, h2, h3, h4; + u64 d0, d1, d2, d3, d4; + u32 c; + + r0 = st->r[0]; + r1 = st->r[1]; + r2 = st->r[2]; + r3 = st->r[3]; + r4 = st->r[4]; + + s1 = r1 * 5; + s2 = r2 * 5; + s3 = r3 * 5; + s4 = r4 * 5; + + h0 = st->h[0]; + h1 = st->h[1]; + h2 = st->h[2]; + h3 = st->h[3]; + h4 = st->h[4]; + + while (bytes >= POLY1305_REF_BLOCKSIZE) + { + /* h += m[i] */ + h0 += (buf_get_le32 (m + 0)) & 0x3ffffff; + h1 += (buf_get_le32 (m + 3) >> 2) & 0x3ffffff; + h2 += (buf_get_le32 (m + 6) >> 4) & 0x3ffffff; + h3 += (buf_get_le32 (m + 9) >> 6) & 0x3ffffff; + h4 += (buf_get_le32 (m + 12) >> 8) | hibit; + + /* h *= r */ + d0 = + ((u64) h0 * r0) + ((u64) h1 * s4) + + ((u64) h2 * s3) + ((u64) h3 * s2) + ((u64) h4 * s1); + d1 = + ((u64) h0 * r1) + ((u64) h1 * r0) + + ((u64) h2 * s4) + ((u64) h3 * s3) + ((u64) h4 * s2); + d2 = + ((u64) h0 * r2) + ((u64) h1 * r1) + + ((u64) h2 * r0) + ((u64) h3 * s4) + ((u64) h4 * s3); + d3 = + ((u64) h0 * r3) + ((u64) h1 * r2) + + ((u64) h2 * r1) + ((u64) h3 * r0) + ((u64) h4 * s4); + d4 = + ((u64) h0 * r4) + ((u64) h1 * r3) + + ((u64) h2 * r2) + ((u64) h3 * r1) + ((u64) h4 * r0); + + /* (partial) h %= p */ + c = (u32) (d0 >> 26); + h0 = (u32) d0 & 0x3ffffff; + d1 += c; + c = (u32) (d1 >> 26); + h1 = (u32) d1 & 0x3ffffff; + d2 += c; + c = (u32) (d2 >> 26); + h2 = (u32) d2 & 0x3ffffff; + d3 += c; + c = (u32) (d3 >> 26); + h3 = (u32) d3 & 0x3ffffff; + d4 += c; + c = (u32) (d4 >> 26); + h4 = (u32) d4 & 0x3ffffff; + h0 += c * 5; + c = (h0 >> 26); + h0 = h0 & 0x3ffffff; + h1 += c; + + m += POLY1305_REF_BLOCKSIZE; + bytes -= POLY1305_REF_BLOCKSIZE; + } + + st->h[0] = h0; + st->h[1] = h1; + st->h[2] = h2; + st->h[3] = h3; + st->h[4] = h4; + + return (16 * sizeof (u32) + 5 * sizeof (u64) + 5 * sizeof (void *)); +} + + +static unsigned int +poly1305_finish_ext_ref32 (void *state, const byte * m, + size_t remaining, byte mac[POLY1305_TAGLEN]) +{ + poly1305_state_ref32_t *st = (poly1305_state_ref32_t *) state; + u32 h0, h1, h2, h3, h4, c; + u32 g0, g1, g2, g3, g4; + u64 f; + u32 mask; + unsigned int burn = 0; + + /* process the remaining block */ + if (remaining) + { + byte final[POLY1305_REF_BLOCKSIZE] = { 0 }; + size_t i; + for (i = 0; i < remaining; i++) + final[i] = m[i]; + final[remaining] = 1; + st->final = 1; + burn = poly1305_blocks_ref32 (st, final, POLY1305_REF_BLOCKSIZE); + } + + /* fully carry h */ + h0 = st->h[0]; + h1 = st->h[1]; + h2 = st->h[2]; + h3 = st->h[3]; + h4 = st->h[4]; + + c = h1 >> 26; + h1 = h1 & 0x3ffffff; + h2 += c; + c = h2 >> 26; + h2 = h2 & 0x3ffffff; + h3 += c; + c = h3 >> 26; + h3 = h3 & 0x3ffffff; + h4 += c; + c = h4 >> 26; + h4 = h4 & 0x3ffffff; + h0 += c * 5; + c = h0 >> 26; + h0 = h0 & 0x3ffffff; + h1 += c; + + /* compute h + -p */ + g0 = h0 + 5; + c = g0 >> 26; + g0 &= 0x3ffffff; + g1 = h1 + c; + c = g1 >> 26; + g1 &= 0x3ffffff; + g2 = h2 + c; + c = g2 >> 26; + g2 &= 0x3ffffff; + g3 = h3 + c; + c = g3 >> 26; + g3 &= 0x3ffffff; + g4 = h4 + c - (1 << 26); + + /* select h if h < p, or h + -p if h >= p */ + mask = (g4 >> ((sizeof (u32) * 8) - 1)) - 1; + g0 &= mask; + g1 &= mask; + g2 &= mask; + g3 &= mask; + g4 &= mask; + mask = ~mask; + h0 = (h0 & mask) | g0; + h1 = (h1 & mask) | g1; + h2 = (h2 & mask) | g2; + h3 = (h3 & mask) | g3; + h4 = (h4 & mask) | g4; + + /* h = h % (2^128) */ + h0 = ((h0) | (h1 << 26)) & 0xffffffff; + h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff; + h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff; + h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; + + /* mac = (h + pad) % (2^128) */ + f = (u64) h0 + st->pad[0]; + h0 = (u32) f; + f = (u64) h1 + st->pad[1] + (f >> 32); + h1 = (u32) f; + f = (u64) h2 + st->pad[2] + (f >> 32); + h2 = (u32) f; + f = (u64) h3 + st->pad[3] + (f >> 32); + h3 = (u32) f; + + buf_put_le32 (mac + 0, h0); + buf_put_le32 (mac + 4, h1); + buf_put_le32 (mac + 8, h2); + buf_put_le32 (mac + 12, h3); + + /* zero out the state */ + st->h[0] = 0; + st->h[1] = 0; + st->h[2] = 0; + st->h[3] = 0; + st->h[4] = 0; + st->r[0] = 0; + st->r[1] = 0; + st->r[2] = 0; + st->r[3] = 0; + st->r[4] = 0; + st->pad[0] = 0; + st->pad[1] = 0; + st->pad[2] = 0; + st->pad[3] = 0; + + /* burn_stack */ + return (13 * sizeof (u32) + sizeof (u64) + + POLY1305_REF_BLOCKSIZE + 6 * sizeof (void *)) + burn; +} + + +static const poly1305_ops_t poly1305_default_ops = { + POLY1305_REF_BLOCKSIZE, + poly1305_init_ext_ref32, + poly1305_blocks_ref32, + poly1305_finish_ext_ref32 +}; + +#else /* !HAVE_U64_TYPEDEF */ + +/* Reference unoptimized poly1305 implementation using 8 bit * 8 bit = 16 bit + * multiplication and 16 bit addition, used when we don't have 'u64'. + */ + +typedef struct poly1305_state_ref8_t +{ + byte h[17]; + byte r[17]; + byte pad[17]; + byte final; +} poly1305_state_ref8_t; + + +static void +poly1305_init_ext_ref8 (void *state, const poly1305_key_t * key) +{ + poly1305_state_ref8_t *st = (poly1305_state_ref8_t *) state; + size_t i; + + /* h = 0 */ + for (i = 0; i < 17; i++) + st->h[i] = 0; + + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ + st->r[0] = key->b[0]; + st->r[1] = key->b[1]; + st->r[2] = key->b[2]; + st->r[3] = key->b[3] & 0x0f; + st->r[4] = key->b[4] & 0xfc; + st->r[5] = key->b[5]; + st->r[6] = key->b[6]; + st->r[7] = key->b[7] & 0x0f; + st->r[8] = key->b[8] & 0xfc; + st->r[9] = key->b[9]; + st->r[10] = key->b[10]; + st->r[11] = key->b[11] & 0x0f; + st->r[12] = key->b[12] & 0xfc; + st->r[13] = key->b[13]; + st->r[14] = key->b[14]; + st->r[15] = key->b[15] & 0x0f; + st->r[16] = 0; + + /* save pad for later */ + for (i = 0; i < 16; i++) + st->pad[i] = key->b[i + 16]; + st->pad[16] = 0; + + st->final = 0; +} + + +static void +poly1305_add_ref8 (byte h[17], const byte c[17]) +{ + u16 u; + unsigned int i; + for (u = 0, i = 0; i < 17; i++) + { + u += (u16) h[i] + (u16) c[i]; + h[i] = (byte) u & 0xff; + u >>= 8; + } +} + + +static void +poly1305_squeeze_ref8 (byte h[17], u32 hr[17]) +{ + u32 u; + unsigned int i; + u = 0; + for (i = 0; i < 16; i++) + { + u += hr[i]; + h[i] = (byte) u & 0xff; + u >>= 8; + } + u += hr[16]; + h[16] = (byte) u & 0x03; + u >>= 2; + u += (u << 2); /* u *= 5; */ + for (i = 0; i < 16; i++) + { + u += h[i]; + h[i] = (byte) u & 0xff; + u >>= 8; + } + h[16] += (byte) u; +} + + +static void +poly1305_freeze_ref8 (byte h[17]) +{ + static const byte minusp[17] = { + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfc + }; + byte horig[17], negative; + unsigned int i; + + /* compute h + -p */ + for (i = 0; i < 17; i++) + horig[i] = h[i]; + poly1305_add_ref8 (h, minusp); + + /* select h if h < p, or h + -p if h >= p */ + negative = -(h[16] >> 7); + for (i = 0; i < 17; i++) + h[i] ^= negative & (horig[i] ^ h[i]); +} + + +static unsigned int +poly1305_blocks_ref8 (void *state, const byte * m, size_t bytes) +{ + poly1305_state_ref8_t *st = (poly1305_state_ref8_t *) state; + const byte hibit = st->final ^ 1; /* 1 << 128 */ + + while (bytes >= POLY1305_REF_BLOCKSIZE) + { + u32 hr[17], u; + byte c[17]; + unsigned int i, j; + + /* h += m */ + for (i = 0; i < 16; i++) + c[i] = m[i]; + c[16] = hibit; + poly1305_add_ref8 (st->h, c); + + /* h *= r */ + for (i = 0; i < 17; i++) + { + u = 0; + for (j = 0; j <= i; j++) + { + u += (u16) st->h[j] * st->r[i - j]; + } + for (j = i + 1; j < 17; j++) + { + u32 v = (u16) st->h[j] * st->r[i + 17 - j]; + v = ((v << 8) + (v << 6)); /* v *= (5 << 6); */ + u += v; + } + hr[i] = u; + } + + /* (partial) h %= p */ + poly1305_squeeze_ref8 (st->h, hr); + + m += POLY1305_REF_BLOCKSIZE; + bytes -= POLY1305_REF_BLOCKSIZE; + } + + /* burn_stack */ + return (18 + 2) * sizeof (u32) + 18 + 6 * sizeof (void *) + + 6 * sizeof (void *); +} + + +static unsigned int +poly1305_finish_ext_ref8 (void *state, const byte * m, size_t remaining, + byte mac[POLY1305_TAGLEN]) +{ + poly1305_state_ref8_t *st = (poly1305_state_ref8_t *) state; + size_t i; + unsigned int burn = 0; + + /* process the remaining block */ + if (remaining) + { + byte final[POLY1305_REF_BLOCKSIZE] = { 0 }; + for (i = 0; i < remaining; i++) + final[i] = m[i]; + final[remaining] = 1; + st->final = 1; + burn = poly1305_blocks_ref8 (st, final, POLY1305_REF_BLOCKSIZE); + } + + /* fully reduce h */ + poly1305_freeze_ref8 (st->h); + + /* h = (h + pad) % (1 << 128) */ + poly1305_add_ref8 (st->h, st->pad); + for (i = 0; i < 16; i++) + mac[i] = st->h[i]; + + /* zero out the state */ + for (i = 0; i < 17; i++) + st->h[i] = 0; + for (i = 0; i < 17; i++) + st->r[i] = 0; + for (i = 0; i < 17; i++) + st->pad[i] = 0; + + /* burn_stack */ + return POLY1305_REF_BLOCKSIZE + 18 + 16 * sizeof (void *) + burn; +} + + +static const poly1305_ops_t poly1305_default_ops = { + POLY1305_REF_BLOCKSIZE, + poly1305_init_ext_ref8, + poly1305_blocks_ref8, + poly1305_finish_ext_ref8 +}; + +#endif /* HAVE_U64_TYPEDEF */ + + + +static inline void * +poly1305_get_state (poly1305_context_t * ctx) +{ + byte *c = ctx->state; + c += POLY1305_STATE_ALIGNMENT - 1; + c -= (uintptr_t) c & (POLY1305_STATE_ALIGNMENT - 1); + return c; +} + + +static void +poly1305_init (poly1305_context_t * ctx, const poly1305_key_t * key) +{ + void *state = poly1305_get_state (ctx); + + ctx->leftover = 0; + + ctx->ops->init_ext (state, key); +} + + +void +_gcry_poly1305_update (poly1305_context_t * ctx, const byte * m, size_t bytes) +{ + void *state = poly1305_get_state (ctx); + unsigned int burn = 0; + size_t block_size = ctx->ops->block_size; + + /* handle leftover */ + if (ctx->leftover) + { + size_t want = (block_size - ctx->leftover); + if (want > bytes) + want = bytes; + buf_cpy (ctx->buffer + ctx->leftover, m, want); + bytes -= want; + m += want; + ctx->leftover += want; + if (ctx->leftover < block_size) + return; + burn = ctx->ops->blocks (state, ctx->buffer, block_size); + ctx->leftover = 0; + } + + /* process full blocks */ + if (bytes >= block_size) + { + size_t want = (bytes & ~(block_size - 1)); + burn = ctx->ops->blocks (state, m, want); + m += want; + bytes -= want; + } + + /* store leftover */ + if (bytes) + { + buf_cpy (ctx->buffer + ctx->leftover, m, bytes); + ctx->leftover += bytes; + } + + if (burn) + _gcry_burn_stack (burn); +} + + +void +_gcry_poly1305_finish (poly1305_context_t * ctx, byte mac[POLY1305_TAGLEN]) +{ + void *state = poly1305_get_state (ctx); + unsigned int burn; + + burn = ctx->ops->finish_ext (state, ctx->buffer, ctx->leftover, mac); + + _gcry_burn_stack (burn); +} + + +gcry_err_code_t +_gcry_poly1305_init (poly1305_context_t * ctx, const byte * key, + size_t keylen) +{ + static int initialized; + static const char *selftest_failed; + poly1305_key_t keytmp; + + if (!initialized) + { + initialized = 1; + selftest_failed = selftest (); + if (selftest_failed) + log_error ("Poly1305 selftest failed (%s)\n", selftest_failed); + } + + if (keylen != POLY1305_KEYLEN) + return GPG_ERR_INV_KEYLEN; + + if (selftest_failed) + return GPG_ERR_SELFTEST_FAILED; + + ctx->ops = &poly1305_default_ops; + + buf_cpy (keytmp.b, key, POLY1305_KEYLEN); + poly1305_init (ctx, &keytmp); + + wipememory (&keytmp, sizeof (keytmp)); + + return 0; +} + + +static void +poly1305_auth (byte mac[POLY1305_TAGLEN], const byte * m, size_t bytes, + const byte * key) +{ + poly1305_context_t ctx; + + memset (&ctx, 0, sizeof (ctx)); + + _gcry_poly1305_init (&ctx, key, POLY1305_KEYLEN); + _gcry_poly1305_update (&ctx, m, bytes); + _gcry_poly1305_finish (&ctx, mac); + + wipememory (&ctx, sizeof (ctx)); +} + + +static const char * +selftest (void) +{ + /* example from nacl */ + static const byte nacl_key[POLY1305_KEYLEN] = { + 0xee, 0xa6, 0xa7, 0x25, 0x1c, 0x1e, 0x72, 0x91, + 0x6d, 0x11, 0xc2, 0xcb, 0x21, 0x4d, 0x3c, 0x25, + 0x25, 0x39, 0x12, 0x1d, 0x8e, 0x23, 0x4e, 0x65, + 0x2d, 0x65, 0x1f, 0xa4, 0xc8, 0xcf, 0xf8, 0x80, + }; + + static const byte nacl_msg[131] = { + 0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73, + 0xc2, 0x96, 0x50, 0xba, 0x32, 0xfc, 0x76, 0xce, + 0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4, + 0x47, 0x6f, 0xb8, 0xc5, 0x31, 0xa1, 0x18, 0x6a, + 0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 0x7b, + 0x4d, 0xa7, 0xf0, 0x11, 0xec, 0x48, 0xc9, 0x72, + 0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2, + 0x27, 0x0d, 0x6f, 0xb8, 0x63, 0xd5, 0x17, 0x38, + 0xb4, 0x8e, 0xee, 0xe3, 0x14, 0xa7, 0xcc, 0x8a, + 0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 0x26, 0xae, + 0x90, 0x22, 0x43, 0x68, 0x51, 0x7a, 0xcf, 0xea, + 0xbd, 0x6b, 0xb3, 0x73, 0x2b, 0xc0, 0xe9, 0xda, + 0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde, + 0x56, 0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3, + 0x79, 0x73, 0xf6, 0x22, 0xa4, 0x3d, 0x14, 0xa6, + 0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74, + 0xe3, 0x55, 0xa5 + }; + + static const byte nacl_mac[16] = { + 0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5, + 0x2a, 0x7d, 0xfb, 0x4b, 0x3d, 0x33, 0x05, 0xd9 + }; + + /* generates a final value of (2^130 - 2) == 3 */ + static const byte wrap_key[POLY1305_KEYLEN] = { + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + static const byte wrap_msg[16] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + static const byte wrap_mac[16] = { + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + /* mac of the macs of messages of length 0 to 256, where the key and messages + * have all their values set to the length + */ + static const byte total_key[POLY1305_KEYLEN] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + static const byte total_mac[16] = { + 0x64, 0xaf, 0xe2, 0xe8, 0xd6, 0xad, 0x7b, 0xbd, + 0xd2, 0x87, 0xf9, 0x7c, 0x44, 0x62, 0x3d, 0x39 + }; + + poly1305_context_t ctx; + poly1305_context_t total_ctx; + byte all_key[POLY1305_KEYLEN]; + byte all_msg[256]; + byte mac[16]; + size_t i, j; + + memset (&ctx, 0, sizeof (ctx)); + memset (&total_ctx, 0, sizeof (total_ctx)); + + memset (mac, 0, sizeof (mac)); + poly1305_auth (mac, nacl_msg, sizeof (nacl_msg), nacl_key); + if (memcmp (nacl_mac, mac, sizeof (nacl_mac)) != 0) + return "Poly1305 test 1 failed."; + + /* SSE2/AVX have a 32 byte block size, but also support 64 byte blocks, so + * make sure everything still works varying between them */ + memset (mac, 0, sizeof (mac)); + _gcry_poly1305_init (&ctx, nacl_key, POLY1305_KEYLEN); + _gcry_poly1305_update (&ctx, nacl_msg + 0, 32); + _gcry_poly1305_update (&ctx, nacl_msg + 32, 64); + _gcry_poly1305_update (&ctx, nacl_msg + 96, 16); + _gcry_poly1305_update (&ctx, nacl_msg + 112, 8); + _gcry_poly1305_update (&ctx, nacl_msg + 120, 4); + _gcry_poly1305_update (&ctx, nacl_msg + 124, 2); + _gcry_poly1305_update (&ctx, nacl_msg + 126, 1); + _gcry_poly1305_update (&ctx, nacl_msg + 127, 1); + _gcry_poly1305_update (&ctx, nacl_msg + 128, 1); + _gcry_poly1305_update (&ctx, nacl_msg + 129, 1); + _gcry_poly1305_update (&ctx, nacl_msg + 130, 1); + _gcry_poly1305_finish (&ctx, mac); + if (memcmp (nacl_mac, mac, sizeof (nacl_mac)) != 0) + return "Poly1305 test 2 failed."; + + memset (mac, 0, sizeof (mac)); + poly1305_auth (mac, wrap_msg, sizeof (wrap_msg), wrap_key); + if (memcmp (wrap_mac, mac, sizeof (nacl_mac)) != 0) + return "Poly1305 test 3 failed."; + + _gcry_poly1305_init (&total_ctx, total_key, POLY1305_KEYLEN); + for (i = 0; i < 256; i++) + { + /* set key and message to 'i,i,i..' */ + for (j = 0; j < sizeof (all_key); j++) + all_key[j] = i; + for (j = 0; j < i; j++) + all_msg[j] = i; + poly1305_auth (mac, all_msg, i, all_key); + _gcry_poly1305_update (&total_ctx, mac, 16); + } + _gcry_poly1305_finish (&total_ctx, mac); + if (memcmp (total_mac, mac, sizeof (total_mac)) != 0) + return "Poly1305 test 4 failed."; + + return NULL; +} diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index d4e9bb2..8648e96 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -1341,7 +1341,9 @@ enum gcry_mac_algos GCRY_MAC_GMAC_CAMELLIA = 402, GCRY_MAC_GMAC_TWOFISH = 403, GCRY_MAC_GMAC_SERPENT = 404, - GCRY_MAC_GMAC_SEED = 405 + GCRY_MAC_GMAC_SEED = 405, + + GCRY_MAC_POLY1305 = 501 }; /* Flags used with the open function. */ diff --git a/tests/basic.c b/tests/basic.c index 406d82d..cc0f4c1 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -5041,6 +5041,8 @@ check_mac (void) const char *key; const char *expect; const char *iv; + unsigned int dlen; + unsigned int klen; } algos[] = { { GCRY_MAC_HMAC_MD5, "what do ya want for nothing?", "Jefe", @@ -5491,6 +5493,109 @@ check_mac (void) "\xc9\xfc\xa7\x29\xab\x60\xad\xa0", "\x20\x4b\xdb\x1b\xd6\x21\x54\xbf\x08\x92\x2a\xaa\x54\xee\xd7\x05", "\x05\xad\x13\xa5\xe2\xc2\xab\x66\x7e\x1a\x6f\xbc" }, + /* from NaCl */ + { GCRY_MAC_POLY1305, + "\x8e\x99\x3b\x9f\x48\x68\x12\x73\xc2\x96\x50\xba\x32\xfc\x76\xce" + "\x48\x33\x2e\xa7\x16\x4d\x96\xa4\x47\x6f\xb8\xc5\x31\xa1\x18\x6a" + "\xc0\xdf\xc1\x7c\x98\xdc\xe8\x7b\x4d\xa7\xf0\x11\xec\x48\xc9\x72" + "\x71\xd2\xc2\x0f\x9b\x92\x8f\xe2\x27\x0d\x6f\xb8\x63\xd5\x17\x38" + "\xb4\x8e\xee\xe3\x14\xa7\xcc\x8a\xb9\x32\x16\x45\x48\xe5\x26\xae" + "\x90\x22\x43\x68\x51\x7a\xcf\xea\xbd\x6b\xb3\x73\x2b\xc0\xe9\xda" + "\x99\x83\x2b\x61\xca\x01\xb6\xde\x56\x24\x4a\x9e\x88\xd5\xf9\xb3" + "\x79\x73\xf6\x22\xa4\x3d\x14\xa6\x59\x9b\x1f\x65\x4c\xb4\x5a\x74" + "\xe3\x55\xa5", + "\xee\xa6\xa7\x25\x1c\x1e\x72\x91\x6d\x11\xc2\xcb\x21\x4d\x3c\x25" + "\x25\x39\x12\x1d\x8e\x23\x4e\x65\x2d\x65\x1f\xa4\xc8\xcf\xf8\x80", + "\xf3\xff\xc7\x70\x3f\x94\x00\xe5\x2a\x7d\xfb\x4b\x3d\x33\x05\xd9" }, + /* from draft-nir-cfrg-chacha20-poly1305-03 */ + { GCRY_MAC_POLY1305, + "Cryptographic Forum Research Group", + "\x85\xd6\xbe\x78\x57\x55\x6d\x33\x7f\x44\x52\xfe\x42\xd5\x06\xa8" + "\x01\x03\x80\x8a\xfb\x0d\xb2\xfd\x4a\xbf\xf6\xaf\x41\x49\xf5\x1b", + "\xa8\x06\x1d\xc1\x30\x51\x36\xc6\xc2\x2b\x8b\xaf\x0c\x01\x27\xa9" }, + { GCRY_MAC_POLY1305, + "'Twas brillig, and the slithy toves\n" + "Did gyre and gimble in the wabe:\n" + "All mimsy were the borogoves,\n" + "And the mome raths outgrabe.", + "\x1c\x92\x40\xa5\xeb\x55\xd3\x8a\xf3\x33\x88\x86\x04\xf6\xb5\xf0" + "\x47\x39\x17\xc1\x40\x2b\x80\x09\x9d\xca\x5c\xbc\x20\x70\x75\xc0", + "\x45\x41\x66\x9a\x7e\xaa\xee\x61\xe7\x08\xdc\x7c\xbc\xc5\xeb\x62" }, + { GCRY_MAC_POLY1305, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + NULL, + 191, 32 }, + { GCRY_MAC_POLY1305, + "Any submission to the IETF intended by the Contributor for " + "publication as all or part of an IETF Internet-Draft or RFC and " + "any statement made within the context of an IETF activity is " + "considered an \"IETF Contribution\". Such statements include " + "oral statements in IETF sessions, as well as written and " + "electronic communications made at any time or place, which are " + "addressed to", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x36\xe5\xf6\xb5\xc5\xe0\x60\x70\xf0\xef\xca\x96\x22\x7a\x86\x3e", + "\x36\xe5\xf6\xb5\xc5\xe0\x60\x70\xf0\xef\xca\x96\x22\x7a\x86\x3e", + NULL, + 0, 32 }, + { GCRY_MAC_POLY1305, + "Any submission to the IETF intended by the Contributor for " + "publication as all or part of an IETF Internet-Draft or RFC and " + "any statement made within the context of an IETF activity is " + "considered an \"IETF Contribution\". Such statements include " + "oral statements in IETF sessions, as well as written and " + "electronic communications made at any time or place, which are " + "addressed to", + "\x36\xe5\xf6\xb5\xc5\xe0\x60\x70\xf0\xef\xca\x96\x22\x7a\x86\x3e" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\xf3\x47\x7e\x7c\xd9\x54\x17\xaf\x89\xa6\xb8\x79\x4c\x31\x0c\xf0", + NULL, + 0, 32 }, + /* from http://cr.yp.to/mac/poly1305-20050329.pdf */ + { GCRY_MAC_POLY1305, + "\xf3\xf6", + "\x85\x1f\xc4\x0c\x34\x67\xac\x0b\xe0\x5c\xc2\x04\x04\xf3\xf7\x00" + "\x58\x0b\x3b\x0f\x94\x47\xbb\x1e\x69\xd0\x95\xb5\x92\x8b\x6d\xbc", + "\xf4\xc6\x33\xc3\x04\x4f\xc1\x45\xf8\x4f\x33\x5c\xb8\x19\x53\xde", + NULL, + 0, 32 }, + { GCRY_MAC_POLY1305, + "", + "\xa0\xf3\x08\x00\x00\xf4\x64\x00\xd0\xc7\xe9\x07\x6c\x83\x44\x03" + "\xdd\x3f\xab\x22\x51\xf1\x1a\xc7\x59\xf0\x88\x71\x29\xcc\x2e\xe7", + "\xdd\x3f\xab\x22\x51\xf1\x1a\xc7\x59\xf0\x88\x71\x29\xcc\x2e\xe7", + NULL, + 0, 32 }, + { GCRY_MAC_POLY1305, + "\x66\x3c\xea\x19\x0f\xfb\x83\xd8\x95\x93\xf3\xf4\x76\xb6\xbc\x24" + "\xd7\xe6\x79\x10\x7e\xa2\x6a\xdb\x8c\xaf\x66\x52\xd0\x65\x61\x36", + "\x48\x44\x3d\x0b\xb0\xd2\x11\x09\xc8\x9a\x10\x0b\x5c\xe2\xc2\x08" + "\x83\x14\x9c\x69\xb5\x61\xdd\x88\x29\x8a\x17\x98\xb1\x07\x16\xef", + "\x0e\xe1\xc1\x6b\xb7\x3f\x0f\x4f\xd1\x98\x81\x75\x3c\x01\xcd\xbe", + NULL, + 0, 32 }, + { GCRY_MAC_POLY1305, + "\xab\x08\x12\x72\x4a\x7f\x1e\x34\x27\x42\xcb\xed\x37\x4d\x94\xd1" + "\x36\xc6\xb8\x79\x5d\x45\xb3\x81\x98\x30\xf2\xc0\x44\x91\xfa\xf0" + "\x99\x0c\x62\xe4\x8b\x80\x18\xb2\xc3\xe4\xa0\xfa\x31\x34\xcb\x67" + "\xfa\x83\xe1\x58\xc9\x94\xd9\x61\xc4\xcb\x21\x09\x5c\x1b\xf9", + "\x12\x97\x6a\x08\xc4\x42\x6d\x0c\xe8\xa8\x24\x07\xc4\xf4\x82\x07" + "\x80\xf8\xc2\x0a\xa7\x12\x02\xd1\xe2\x91\x79\xcb\xcb\x55\x5a\x57", + "\x51\x54\xad\x0d\x2c\xb2\x6e\x01\x27\x4f\xc5\x11\x48\x49\x1f\x1b" }, { 0 }, }; int i; @@ -5500,6 +5605,8 @@ check_mac (void) for (i = 0; algos[i].algo; i++) { + size_t klen, dlen; + if (gcry_mac_test_algo (algos[i].algo)) { show_mac_not_available (algos[i].algo); @@ -5520,13 +5627,14 @@ check_mac (void) algos[i].algo, (int)strlen(algos[i].key), (int)strlen(algos[i].data)); - check_one_mac (algos[i].algo, algos[i].data, strlen (algos[i].data), - algos[i].key, strlen(algos[i].key), algos[i].iv, - algos[i].iv ? strlen(algos[i].iv) : 0, + klen = algos[i].klen ? algos[i].klen : strlen(algos[i].key); + dlen = algos[i].dlen ? algos[i].dlen : strlen (algos[i].data); + + check_one_mac (algos[i].algo, algos[i].data, dlen, algos[i].key, klen, + algos[i].iv, algos[i].iv ? strlen(algos[i].iv) : 0, algos[i].expect, 0); - check_one_mac (algos[i].algo, algos[i].data, strlen (algos[i].data), - algos[i].key, strlen(algos[i].key), algos[i].iv, - algos[i].iv ? strlen(algos[i].iv) : 0, + check_one_mac (algos[i].algo, algos[i].data, dlen, algos[i].key, klen, + algos[i].iv, algos[i].iv ? strlen(algos[i].iv) : 0, algos[i].expect, 1); } diff --git a/tests/bench-slope.c b/tests/bench-slope.c index bd05064..3d8ae37 100644 --- a/tests/bench-slope.c +++ b/tests/bench-slope.c @@ -1405,7 +1405,7 @@ mac_bench (char **argv, int argc) } else { - for (i = 1; i < 500; i++) + for (i = 1; i < 600; i++) if (!gcry_mac_test_algo (i)) _mac_bench (i); } diff --git a/tests/benchmark.c b/tests/benchmark.c index 5efc083..9fd716d 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -461,7 +461,7 @@ mac_bench ( const char *algoname ) if (!algoname) { - for (i=1; i < 500; i++) + for (i=1; i < 600; i++) if (in_fips_mode && i == GCRY_MAC_HMAC_MD5) ; /* Don't use MD5 in fips mode. */ else if ( !gcry_mac_test_algo (i) ) ----------------------------------------------------------------------- Summary of changes: cipher/Makefile.am | 5 +- cipher/cipher-internal.h | 38 +++ cipher/cipher-poly1305.c | 296 +++++++++++++++++ cipher/cipher.c | 51 ++- cipher/mac-internal.h | 32 +- cipher/mac-poly1305.c | 359 +++++++++++++++++++++ cipher/mac.c | 6 + cipher/poly1305-internal.h | 93 ++++++ cipher/poly1305.c | 766 ++++++++++++++++++++++++++++++++++++++++++++ src/gcrypt.h.in | 30 +- tests/basic.c | 472 ++++++++++++++++++++++++++- tests/bench-slope.c | 123 ++++++- tests/benchmark.c | 14 +- 13 files changed, 2244 insertions(+), 41 deletions(-) create mode 100644 cipher/cipher-poly1305.c create mode 100644 cipher/mac-poly1305.c create mode 100644 cipher/poly1305-internal.h create mode 100644 cipher/poly1305.c hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Fri May 16 21:14:54 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Fri, 16 May 2014 21:14:54 +0200 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-423-gd2d9d4f 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 d2d9d4fb60e3f2160af6252335364d3aac4b7d17 (commit) via 8b90d79818355b81ce223e1cb96cd0c939096fe2 (commit) from 25036ec6abbc0c9d0003dcfe227724038c35a304 (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 d2d9d4fb60e3f2160af6252335364d3aac4b7d17 Author: Werner Koch Date: Fri May 16 21:14:03 2014 +0200 keyserver: Improve support for hkps pools. * dirmngr/ks-engine-hkp.c (hostinfo_s): Add fields cname, v4addr, and v6addr. (create_new_hostinfo): Clear them. (my_getnameinfo): Add args numeric and r_isnumeric. (is_ip_address): New. (map_host): Add arg r_host. Rewrite the code to handle pools in a special way. (ks_hkp_print_hosttable): Change format of help info output. (make_host_part): Add arg optional r_httphost. (send_request): Add arg httphost. (ks_hkp_search, ks_hkp_get, ks_hkp_put): Get httphost and pass it to send_request. -- This changes quite some things on how the hostinfo is maintained. However, it might be better to rework the data structures and have one entry per IP address instead of this clumsy patch. diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c index 541c46f..3c25953 100644 --- a/dirmngr/ks-engine-hkp.c +++ b/dirmngr/ks-engine-hkp.c @@ -69,12 +69,20 @@ struct hostinfo_s int *pool; /* A -1 terminated array with indices into HOSTTABLE or NULL if NAME is not a pool name. */ - int poolidx; /* Index into POOL with the used host. */ + int poolidx; /* Index into POOL with the used host. -1 if not set. */ unsigned int v4:1; /* Host supports AF_INET. */ unsigned int v6:1; /* Host supports AF_INET6. */ unsigned int dead:1; /* Host is currently unresponsive. */ - time_t died_at; /* The time the host was marked dead. IF this is + time_t died_at; /* The time the host was marked dead. If this is 0 the host has been manually marked dead. */ + char *cname; /* Canonical name of the host. Only set if this + is a pool. */ + char *v4addr; /* A string with the v4 IP address of the host. + NULL if NAME has a numeric IP address or no v4 + address is available. */ + char *v6addr; /* A string with the v6 IP address of the host. + NULL if NAME has a numeric IP address or no v4 + address is available. */ char name[1]; /* The hostname. */ }; @@ -110,6 +118,9 @@ create_new_hostinfo (const char *name) hi->v6 = 0; hi->dead = 0; hi->died_at = 0; + hi->cname = NULL; + hi->v4addr = NULL; + hi->v6addr = NULL; /* Add it to the hosttable. */ for (idx=0; idx < hosttable_size; idx++) @@ -217,19 +228,28 @@ select_random_host (int *table) /* Simplified version of getnameinfo which also returns a numeric hostname inside of brackets. The caller should provide a buffer - for TMPHOST which is 2 bytes larger than the the largest hostname. - returns 0 on success or an EAI error code. */ + for HOST which is 2 bytes larger than the largest hostname. If + NUMERIC is true the returned value is numeric IP address. Returns + 0 on success or an EAI error code. True is stored at R_ISNUMERIC + if HOST has a numeric IP address. */ static int -my_getnameinfo (struct addrinfo *ai, char *host, size_t hostlen) +my_getnameinfo (struct addrinfo *ai, char *host, size_t hostlen, + int numeric, int *r_isnumeric) { int ec; char *p; + *r_isnumeric = 0; + if (hostlen < 5) return EAI_OVERFLOW; - ec = getnameinfo (ai->ai_addr, ai->ai_addrlen, - host, hostlen, NULL, 0, NI_NAMEREQD); + if (numeric) + ec = EAI_NONAME; + else + ec = getnameinfo (ai->ai_addr, ai->ai_addrlen, + host, hostlen, NULL, 0, NI_NAMEREQD); + if (!ec && *host == '[') ec = EAI_FAIL; /* A name may never start with a bracket. */ else if (ec == EAI_NONAME) @@ -244,28 +264,66 @@ my_getnameinfo (struct addrinfo *ai, char *host, size_t hostlen) p, hostlen, NULL, 0, NI_NUMERICHOST); if (!ec && ai->ai_family == AF_INET6) strcat (host, "]"); + + *r_isnumeric = 1; } return ec; } +/* Check whether NAME is an IP address. */ +static int +is_ip_address (const char *name) +{ + int ndots, n; + + if (*name == '[') + return 1; + /* Check whether it is legacy IP address. */ + if (*name == '.') + return 0; /* No. */ + ndots = n = 0; + for (; *name; name++) + { + if (*name == '.') + { + if (name[1] == '.') + return 0; /* No. */ + if (atoi (name+1) > 255) + return 0; /* Value too large. */ + ndots++; + n = 0; + } + else if (!strchr ("012345678", *name)) + return 0; /* Not a digit. */ + else if (++n > 3) + return 0; /* More than 3 digits. */ + } + return !!(ndots == 3); +} + + /* Map the host name NAME to the actual to be used host name. This allows us to manage round robin DNS names. We use our own strategy to choose one of the hosts. For example we skip those hosts which failed for some time and we stick to one host for a time independent of DNS retry times. If FORCE_RESELECT is true a new host is always selected. If R_HTTPFLAGS is not NULL if will - received flags which are to be passed to http_open. */ + receive flags which are to be passed to http_open. If R_HOST is + not NULL a malloced name of the pool is stored or NULL if it is not + a pool. */ static char * map_host (ctrl_t ctrl, const char *name, int force_reselect, - unsigned int *r_httpflags) + unsigned int *r_httpflags, char **r_host) { hostinfo_t hi; int idx; if (r_httpflags) *r_httpflags = 0; + if (r_host) + *r_host = NULL; /* No hostname means localhost. */ if (!name || !*name) @@ -280,6 +338,7 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect, int *reftbl; size_t reftblsize; int refidx; + int is_pool = 0; reftblsize = 100; reftbl = xtrymalloc (reftblsize * sizeof *reftbl); @@ -298,13 +357,40 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect, /* Find all A records for this entry and put them into the pool list - if any. */ memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; + /* We can't use the the AI_IDN flag because that does the + conversion using the current locale. However, GnuPG always + used UTF-8. To support IDN we would need to make use of the + libidn API. */ if (!getaddrinfo (name, NULL, &hints, &aibuf)) { + int n_v6, n_v4; + + /* First figure out whether this is a pool. For a pool we + use a different strategy than for a plains erver: We use + the canonical name of the pool as the virtual host along + with the IP addresses. If it is not a pool, we use the + specified name. */ + n_v6 = n_v4 = 0; for (ai = aibuf; ai; ai = ai->ai_next) { - char tmphost[NI_MAXHOST]; + if (ai->ai_family != AF_INET6) + n_v6++; + else if (ai->ai_family != AF_INET) + n_v4++; + } + if (n_v6 > 1 || n_v4 > 1) + is_pool = 1; + if (is_pool && aibuf->ai_canonname) + hi->cname = xtrystrdup (aibuf->ai_canonname); + + for (ai = aibuf; ai; ai = ai->ai_next) + { + char tmphost[NI_MAXHOST + 2]; int tmpidx; + int is_numeric; int ec; int i; @@ -312,7 +398,28 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect, continue; dirmngr_tick (ctrl); - if ((ec = my_getnameinfo (ai, tmphost, sizeof tmphost))) + + if (!is_pool && !is_ip_address (name)) + { + /* This is a hostname but not a pool. Use the name + as given without going through getnameinfo. */ + if (strlen (name)+1 > sizeof tmphost) + { + ec = EAI_SYSTEM; + gpg_err_set_errno (EINVAL); + } + else + { + ec = 0; + strcpy (tmphost, name); + } + is_numeric = 0; + } + else + ec = my_getnameinfo (ai, tmphost, sizeof tmphost, + 0, &is_numeric); + + if (ec) { log_info ("getnameinfo failed while checking '%s': %s\n", name, gai_strerror (ec)); @@ -324,15 +431,49 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect, } else { + tmpidx = find_hostinfo (tmphost); + log_info ("getnameinfo returned for '%s': '%s'%s\n", + name, tmphost, + tmpidx == -1? "" : " [already known]"); + + if (tmpidx == -1) /* Create a new entry. */ + tmpidx = create_new_hostinfo (tmphost); - if ((tmpidx = find_hostinfo (tmphost)) != -1) + if (tmpidx == -1) + { + log_error ("map_host for '%s' problem: %s - '%s'" + " [ignored]\n", + name, strerror (errno), tmphost); + } + else /* Set or update the entry. */ { - log_info ("getnameinfo returned for '%s': '%s'" - " [already known]\n", name, tmphost); - if (ai->ai_family == AF_INET) - hosttable[tmpidx]->v4 = 1; + char *ipaddr = NULL; + + if (!is_numeric) + { + ec = my_getnameinfo (ai, tmphost, sizeof tmphost, + 1, &is_numeric); + if (!ec && !(ipaddr = xtrystrdup (tmphost))) + ec = EAI_SYSTEM; + if (ec) + log_info ("getnameinfo failed: %s\n", + gai_strerror (ec)); + } + if (ai->ai_family == AF_INET6) - hosttable[tmpidx]->v6 = 1; + { + hosttable[tmpidx]->v6 = 1; + xfree (hosttable[tmpidx]->v6addr); + hosttable[tmpidx]->v6addr = ipaddr; + } + else if (ai->ai_family == AF_INET) + { + hosttable[tmpidx]->v4 = 1; + xfree (hosttable[tmpidx]->v4addr); + hosttable[tmpidx]->v4addr = ipaddr; + } + else + BUG (); for (i=0; i < refidx; i++) if (reftbl[i] == tmpidx) @@ -340,35 +481,12 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect, if (!(i < refidx) && tmpidx != idx) reftbl[refidx++] = tmpidx; } - else - { - log_info ("getnameinfo returned for '%s': '%s'\n", - name, tmphost); - /* Create a new entry. */ - tmpidx = create_new_hostinfo (tmphost); - if (tmpidx == -1) - log_error ("map_host for '%s' problem: %s - '%s'" - " [ignored]\n", - name, strerror (errno), tmphost); - else - { - if (ai->ai_family == AF_INET) - hosttable[tmpidx]->v4 = 1; - if (ai->ai_family == AF_INET6) - hosttable[tmpidx]->v6 = 1; - - for (i=0; i < refidx; i++) - if (reftbl[i] == tmpidx) - break; - if (!(i < refidx) && tmpidx != idx) - reftbl[refidx++] = tmpidx; - } - } } } + freeaddrinfo (aibuf); } reftbl[refidx] = -1; - if (refidx) + if (refidx && is_pool) { assert (!hi->pool); hi->pool = xtryrealloc (reftbl, (refidx+1) * sizeof *reftbl); @@ -423,12 +541,16 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect, supports IPv, we explicit set the corresponding http flags. The reason for this is that a host might be listed in a pool as not v6 only but actually support v6 when later - resolved the name is resolved by our http layer. */ + the name is resolved by our http layer. */ if (!hi->v4) *r_httpflags |= HTTP_FLAG_IGNORE_IPv4; if (!hi->v6) *r_httpflags |= HTTP_FLAG_IGNORE_IPv6; } + + if (r_host && hi->pool && hi->cname) + *r_host = xtrystrdup (hi->cname); + return xtrystrdup (hi->name); } @@ -571,7 +693,7 @@ ks_hkp_print_hosttable (ctrl_t ctrl) char *p, *died; const char *diedstr; - err = ks_print_help (ctrl, "hosttable (idx, ipv4, ipv6, dead, name, time):"); + err = ks_print_help (ctrl, "hosttable (idx, ipv6, ipv4, dead, name, time):"); if (err) return err; @@ -586,16 +708,26 @@ ks_hkp_print_hosttable (ctrl_t ctrl) } else diedstr = died = NULL; - err = ks_printf_help (ctrl, "%3d %s %s %s %s%s%s%s\n", - idx, hi->v4? "4":" ", hi->v6? "6":" ", - hi->dead? "d":" ", hi->name, + err = ks_printf_help (ctrl, "%3d %s %s %s %s%s%s%s%s%s%s%s\n", + idx, hi->v6? "6":" ", hi->v4? "4":" ", + hi->dead? "d":" ", + hi->name, + hi->v6addr? " v6=":"", + hi->v6addr? hi->v6addr:"", + hi->v4addr? " v4=":"", + hi->v4addr? hi->v4addr:"", diedstr? " (":"", diedstr? diedstr:"", diedstr? ")":"" ); xfree (died); + if (err) + return err; + if (hi->cname) + err = ks_printf_help (ctrl, " . %s", hi->cname); if (err) return err; + if (hi->pool) { init_membuf (&mb, 256); @@ -644,13 +776,15 @@ ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri) } -/* Build the remote part or the URL from SCHEME, HOST and an optional +/* Build the remote part of the URL from SCHEME, HOST and an optional PORT. Returns an allocated string or NULL on failure and sets - ERRNO. */ + ERRNO. If R_HTTPHOST is not NULL it receive a mallcoed string with + the poolname. */ static char * make_host_part (ctrl_t ctrl, const char *scheme, const char *host, unsigned short port, - int force_reselect, unsigned int *r_httpflags) + int force_reselect, + unsigned int *r_httpflags, char **r_httphost) { char portstr[10]; char *hostname; @@ -674,7 +808,7 @@ make_host_part (ctrl_t ctrl, /*fixme_do_srv_lookup ()*/ } - hostname = map_host (ctrl, host, force_reselect, r_httpflags); + hostname = map_host (ctrl, host, force_reselect, r_httpflags, r_httphost); if (!hostname) return NULL; @@ -693,7 +827,8 @@ ks_hkp_resolve (ctrl_t ctrl, parsed_uri_t uri) gpg_error_t err; char *hostport = NULL; - hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port, 1, NULL); + hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port, 1, + NULL, NULL); if (!hostport) { err = gpg_error_from_syserror (); @@ -739,12 +874,13 @@ ks_hkp_housekeeping (time_t curtime) /* Send an HTTP request. On success returns an estream object at - R_FP. HOSTPORTSTR is only used for diagnostics. If POST_CB is not + R_FP. HOSTPORTSTR is only used for diagnostics. If HTTPHOST is + not NULL it will be used as HTTP "Host" header. If POST_CB is not NULL a post request is used and that callback is called to allow writing the post data. */ static gpg_error_t send_request (ctrl_t ctrl, const char *request, const char *hostportstr, - unsigned int httpflags, + const char *httphost, unsigned int httpflags, gpg_error_t (*post_cb)(void *, http_t), void *post_cb_value, estream_t *r_fp) { @@ -765,7 +901,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr, err = http_open (&http, post_cb? HTTP_REQ_POST : HTTP_REQ_GET, request, - NULL, + httphost, /* fixme: AUTH */ NULL, httpflags, /* fixme: proxy*/ NULL, @@ -987,6 +1123,7 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern, estream_t fp = NULL; int reselect; unsigned int httpflags; + char *httphost = NULL; unsigned int tries = SEND_REQUEST_RETRIES; *r_fp = NULL; @@ -1035,8 +1172,9 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern, char *searchkey; xfree (hostport); + xfree (httphost); httphost = NULL; hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port, - reselect, &httpflags); + reselect, &httpflags, &httphost); if (!hostport) { err = gpg_error_from_syserror (); @@ -1064,7 +1202,8 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern, } /* Send the request. */ - err = send_request (ctrl, request, hostport, httpflags, NULL, NULL, &fp); + err = send_request (ctrl, request, hostport, httphost, httpflags, + NULL, NULL, &fp); if (handle_send_request_error (err, request, &tries)) { reselect = 1; @@ -1104,6 +1243,7 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern, es_fclose (fp); xfree (request); xfree (hostport); + xfree (httphost); return err; } @@ -1123,6 +1263,7 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp) char *request = NULL; estream_t fp = NULL; int reselect; + char *httphost = NULL; unsigned int httpflags; unsigned int tries = SEND_REQUEST_RETRIES; @@ -1174,8 +1315,9 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp) again: /* Build the request string. */ xfree (hostport); + xfree (httphost); httphost = NULL; hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port, - reselect, &httpflags); + reselect, &httpflags, &httphost); if (!hostport) { err = gpg_error_from_syserror (); @@ -1195,7 +1337,8 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp) } /* Send the request. */ - err = send_request (ctrl, request, hostport, httpflags, NULL, NULL, &fp); + err = send_request (ctrl, request, hostport, httphost, httpflags, + NULL, NULL, &fp); if (handle_send_request_error (err, request, &tries)) { reselect = 1; @@ -1216,6 +1359,7 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp) es_fclose (fp); xfree (request); xfree (hostport); + xfree (httphost); xfree (searchkey); return err; } @@ -1263,6 +1407,7 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen) struct put_post_parm_s parm; char *armored = NULL; int reselect; + char *httphost = NULL; unsigned int httpflags; unsigned int tries = SEND_REQUEST_RETRIES; @@ -1285,8 +1430,9 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen) reselect = 0; again: xfree (hostport); + xfree (httphost); httphost = NULL; hostport = make_host_part (ctrl, uri->scheme, uri->host, uri->port, - reselect, &httpflags); + reselect, &httpflags, &httphost); if (!hostport) { err = gpg_error_from_syserror (); @@ -1302,7 +1448,8 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen) } /* Send the request. */ - err = send_request (ctrl, request, hostport, 0, put_post_cb, &parm, &fp); + err = send_request (ctrl, request, hostport, httphost, 0, + put_post_cb, &parm, &fp); if (handle_send_request_error (err, request, &tries)) { reselect = 1; @@ -1317,5 +1464,6 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen) xfree (armored); xfree (request); xfree (hostport); + xfree (httphost); return err; } commit 8b90d79818355b81ce223e1cb96cd0c939096fe2 Author: Werner Koch Date: Fri May 16 20:58:58 2014 +0200 http: Allow overriding of the Host header. * common/http.c (http_open): Add arg httphost. (http_open_document): Pass NULL for httphost. (send_request): Add arg httphost. If given, use HTTPHOST instead of SERVER. Use https with a proxy if requested. (http_verify_server_credentials): Do not stop at the first error message. * dirmngr/ocsp.c (do_ocsp_request): Adjust call to http_open. * keyserver/curl-shim.c (curl_easy_perform): Ditto. * dirmngr/ks-engine-http.c (ks_http_fetch): Ditto. * dirmngr/ks-engine-hkp.c (ks_hkp_help): Ditto. diff --git a/common/http.c b/common/http.c index eb95dcb..8a1ad67 100644 --- a/common/http.c +++ b/common/http.c @@ -168,7 +168,8 @@ static int remove_escapes (char *string); static int insert_escapes (char *buffer, const char *string, const char *special); static uri_tuple_t parse_tuple (char *string); -static gpg_error_t send_request (http_t hd, const char *auth,const char *proxy, +static gpg_error_t send_request (http_t hd, const char *httphost, + const char *auth,const char *proxy, const char *srvtag,strlist_t headers); static char *build_rel_path (parsed_uri_t uri); static gpg_error_t parse_response (http_t hd); @@ -643,11 +644,13 @@ http_session_ref (http_session_t sess) } -/* Start a HTTP retrieval and return on success in R_HD a context - pointer for completing the the request and to wait for the - response. */ +/* Start a HTTP retrieval and on success store at R_HD a context + pointer for completing the request and to wait for the response. + If HTTPHOST is not NULL it is used hor the Host header instead of a + Host header derived from the URL. */ gpg_error_t http_open (http_t *r_hd, http_req_t reqtype, const char *url, + const char *httphost, const char *auth, unsigned int flags, const char *proxy, http_session_t session, const char *srvtag, strlist_t headers) { @@ -669,7 +672,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url, err = parse_uri (&hd->uri, url, 0, !!(flags & HTTP_FLAG_FORCE_TLS)); if (!err) - err = send_request (hd, auth, proxy, srvtag, headers); + err = send_request (hd, httphost, auth, proxy, srvtag, headers); if (err) { @@ -868,7 +871,7 @@ http_open_document (http_t *r_hd, const char *document, { gpg_error_t err; - err = http_open (r_hd, HTTP_REQ_GET, document, auth, flags, + err = http_open (r_hd, HTTP_REQ_GET, document, NULL, auth, flags, proxy, session, srvtag, headers); if (err) return err; @@ -1353,7 +1356,7 @@ parse_tuple (char *string) * Returns 0 if the request was successful */ static gpg_error_t -send_request (http_t hd, const char *auth, +send_request (http_t hd, const char *httphost, const char *auth, const char *proxy, const char *srvtag, strlist_t headers) { gpg_error_t err; @@ -1389,7 +1392,7 @@ send_request (http_t hd, const char *auth, int rc; xfree (hd->session->servername); - hd->session->servername = xtrystrdup (server); + hd->session->servername = xtrystrdup (httphost? httphost : server); if (!hd->session->servername) { err = gpg_err_make (default_errsource, gpg_err_code_from_syserror ()); @@ -1549,11 +1552,13 @@ send_request (http_t hd, const char *auth, if (http_proxy && *http_proxy) { request = es_asprintf - ("%s http://%s:%hu%s%s HTTP/1.0\r\n%s%s", + ("%s %s://%s:%hu%s%s HTTP/1.0\r\n%s%s", hd->req_type == HTTP_REQ_GET ? "GET" : hd->req_type == HTTP_REQ_HEAD ? "HEAD" : hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS", - server, port, *p == '/' ? "" : "/", p, + hd->uri->use_tls? "https" : "http", + httphost? httphost : server, + port, *p == '/' ? "" : "/", p, authstr ? authstr : "", proxy_authstr ? proxy_authstr : ""); } @@ -1571,7 +1576,9 @@ send_request (http_t hd, const char *auth, hd->req_type == HTTP_REQ_GET ? "GET" : hd->req_type == HTTP_REQ_HEAD ? "HEAD" : hd->req_type == HTTP_REQ_POST ? "POST" : "OOPS", - *p == '/' ? "" : "/", p, server, portstr, + *p == '/' ? "" : "/", p, + httphost? httphost : server, + portstr, authstr? authstr:""); } xfree (p); @@ -2442,6 +2449,7 @@ http_verify_server_credentials (http_session_t sess) const gnutls_datum_t *certlist; unsigned int certlistlen; gnutls_x509_crt_t cert; + gpg_error_t err = 0; sess->verify.done = 1; sess->verify.status = 0; @@ -2458,27 +2466,35 @@ http_verify_server_credentials (http_session_t sess) if (rc) { log_error ("%s: %s\n", errprefix, gnutls_strerror (rc)); - return gpg_error (GPG_ERR_GENERAL); + if (!err) + err = gpg_error (GPG_ERR_GENERAL); } - if (status) + else if (status) { log_error ("%s: status=0x%04x\n", errprefix, status); sess->verify.status = status; - return gpg_error (GPG_ERR_GENERAL); + if (!err) + err = gpg_error (GPG_ERR_GENERAL); } hostname = sess->servername; if (!hostname || !strchr (hostname, '.')) { log_error ("%s: %s\n", errprefix, "hostname missing"); - return gpg_error (GPG_ERR_GENERAL); + if (!err) + err = gpg_error (GPG_ERR_GENERAL); } certlist = gnutls_certificate_get_peers (sess->tls_session, &certlistlen); if (!certlistlen) { log_error ("%s: %s\n", errprefix, "server did not send a certificate"); - return gpg_error (GPG_ERR_GENERAL); + if (!err) + err = gpg_error (GPG_ERR_GENERAL); + + /* Need to stop here. */ + if (err) + return err; } /* log_debug ("Server sent %u certs\n", certlistlen); */ @@ -2502,7 +2518,10 @@ http_verify_server_credentials (http_session_t sess) rc = gnutls_x509_crt_init (&cert); if (rc < 0) { - return gpg_error (GPG_ERR_GENERAL); + if (!err) + err = gpg_error (GPG_ERR_GENERAL); + if (err) + return err; } rc = gnutls_x509_crt_import (cert, &certlist[0], GNUTLS_X509_FMT_DER); @@ -2510,20 +2529,22 @@ http_verify_server_credentials (http_session_t sess) { log_error ("%s: %s: %s\n", errprefix, "error importing certificate", gnutls_strerror (rc)); - gnutls_x509_crt_deinit (cert); - return gpg_error (GPG_ERR_GENERAL); + if (!err) + err = gpg_error (GPG_ERR_GENERAL); } if (!gnutls_x509_crt_check_hostname (cert, hostname)) { log_error ("%s: %s\n", errprefix, "hostname does not match"); - gnutls_x509_crt_deinit (cert); - return gpg_error (GPG_ERR_GENERAL); + log_info ("(expected '%s')\n", hostname); + if (!err) + err = gpg_error (GPG_ERR_GENERAL); } gnutls_x509_crt_deinit (cert); - sess->verify.rc = 0; - return 0; /* Verification succeeded. */ + if (!err) + sess->verify.rc = 0; + return err; #else /*!HTTP_USE_GNUTLS*/ (void)sess; return gpg_error (GPG_ERR_NOT_IMPLEMENTED); diff --git a/common/http.h b/common/http.h index b6471b6..acfdc0f 100644 --- a/common/http.h +++ b/common/http.h @@ -110,6 +110,7 @@ gpg_error_t http_raw_connect (http_t *r_hd, gpg_error_t http_open (http_t *r_hd, http_req_t reqtype, const char *url, + const char *httphost, const char *auth, unsigned int flags, const char *proxy, diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c index 8c3384d..541c46f 100644 --- a/dirmngr/ks-engine-hkp.c +++ b/dirmngr/ks-engine-hkp.c @@ -765,6 +765,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr, err = http_open (&http, post_cb? HTTP_REQ_POST : HTTP_REQ_GET, request, + NULL, /* fixme: AUTH */ NULL, httpflags, /* fixme: proxy*/ NULL, diff --git a/dirmngr/ks-engine-http.c b/dirmngr/ks-engine-http.c index a9399a1..aed3aaa 100644 --- a/dirmngr/ks-engine-http.c +++ b/dirmngr/ks-engine-http.c @@ -68,6 +68,7 @@ ks_http_fetch (ctrl_t ctrl, const char *url, estream_t *r_fp) err = http_open (&http, HTTP_REQ_GET, url, + /* httphost */ NULL, /* fixme: AUTH */ NULL, 0, /* fixme: proxy*/ NULL, diff --git a/dirmngr/ocsp.c b/dirmngr/ocsp.c index b941b5c..0d506ef 100644 --- a/dirmngr/ocsp.c +++ b/dirmngr/ocsp.c @@ -165,7 +165,7 @@ do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_md_hd_t md, } once_more: - err = http_open (&http, HTTP_REQ_POST, url, NULL, + err = http_open (&http, HTTP_REQ_POST, url, NULL, NULL, (opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0), opt.http_proxy, NULL, NULL, NULL); if (err) diff --git a/dirmngr/server.c b/dirmngr/server.c index bdfb755..6cf4dd6 100644 --- a/dirmngr/server.c +++ b/dirmngr/server.c @@ -298,7 +298,7 @@ skip_options (char *line) } -/* Return an error if the assuan context does not belong to teh owner +/* Return an error if the assuan context does not belong to the owner of the process or to root. On error FAILTEXT is set as Assuan error string. */ static gpg_error_t diff --git a/keyserver/curl-shim.c b/keyserver/curl-shim.c index 500d9f5..696efe2 100644 --- a/keyserver/curl-shim.c +++ b/keyserver/curl-shim.c @@ -198,7 +198,7 @@ curl_easy_perform(CURL *curl) if(curl->flags.post) { - rc = http_open (&curl->hd, HTTP_REQ_POST, curl->url, curl->auth, + rc = http_open (&curl->hd, HTTP_REQ_POST, curl->url, NULL, curl->auth, 0, proxy, NULL, curl->srvtag, curl->headers?curl->headers->list:NULL); if (!rc) @@ -222,7 +222,7 @@ curl_easy_perform(CURL *curl) } else { - rc = http_open (&curl->hd, HTTP_REQ_GET, curl->url, curl->auth, + rc = http_open (&curl->hd, HTTP_REQ_GET, curl->url, NULL, curl->auth, 0, proxy, NULL, curl->srvtag, curl->headers?curl->headers->list:NULL); if (!rc) @@ -282,7 +282,7 @@ curl_easy_perform(CURL *curl) err=CURLE_COULDNT_CONNECT; break; } - + return handle_error(curl,err,errstr); } ----------------------------------------------------------------------- Summary of changes: common/http.c | 67 ++++++++---- common/http.h | 1 + dirmngr/ks-engine-hkp.c | 269 +++++++++++++++++++++++++++++++++++----------- dirmngr/ks-engine-http.c | 1 + dirmngr/ocsp.c | 2 +- dirmngr/server.c | 2 +- keyserver/curl-shim.c | 6 +- 7 files changed, 260 insertions(+), 88 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Sun May 18 11:57:58 2014 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sun, 18 May 2014 11:57:58 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-80-gbf49439 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 bf4943932dae95a0573b63bf32a9b9acd5a6ddf3 (commit) via 323b1eb80ff3396d83fedbe5bba9a4e6c412d192 (commit) via 98f021961ee65669037bc8bb552a69fd78f610fc (commit) via 297532602ed2d881d8fdc393d1961068a143a891 (commit) from e813958419b0ec4439e6caf07d3b2234cffa2bfa (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 bf4943932dae95a0573b63bf32a9b9acd5a6ddf3 Author: Jussi Kivilinna Date: Sat May 17 18:30:39 2014 +0300 Add Poly1305 to documentation * doc/gcrypt.texi: Add documentation for Poly1305 MACs and AEAD mode. -- Signed-off-by: Jussi Kivilinna diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index d202b8b..d59c095 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -1629,6 +1629,11 @@ Galois/Counter Mode (GCM) is an Authenticated Encryption with Associated Data (AEAD) block cipher mode, which is specified in 'NIST Special Publication 800-38D'. + at item GCRY_CIPHER_MODE_POLY1305 + at cindex Poly1305 based AEAD mode +Poly1305 is an Authenticated Encryption with Associated Data (AEAD) +mode, which can be used with ChaCha20 and Salsa20 stream ciphers. + @end table @node Working with cipher handles @@ -1655,12 +1660,13 @@ The cipher mode to use must be specified via @var{mode}. See @xref{Available cipher modes}, for a list of supported cipher modes and the according constants. Note that some modes are incompatible with some algorithms - in particular, stream mode -(@code{GCRY_CIPHER_MODE_STREAM}) only works with stream ciphers. The -block cipher modes (@code{GCRY_CIPHER_MODE_ECB}, +(@code{GCRY_CIPHER_MODE_STREAM}) only works with stream ciphers. +Poly1305 AEAD mode (@code{GCRY_CIPHER_MODE_POLY1305}) only works with +ChaCha and Salsa stream ciphers. The block cipher modes (@code{GCRY_CIPHER_MODE_ECB}, @code{GCRY_CIPHER_MODE_CBC}, @code{GCRY_CIPHER_MODE_CFB}, @code{GCRY_CIPHER_MODE_OFB} and @code{GCRY_CIPHER_MODE_CTR}) will work -with any block cipher algorithm. @code{GCRY_CIPHER_MODE_CCM} and - at code{GCRY_CIPHER_MODE_GCM} modes will only work with block cipher algorithms +with any block cipher algorithm. GCM mode (@code{GCRY_CIPHER_MODE_CCM}) and +CCM mode (@code{GCRY_CIPHER_MODE_GCM}) will only work with block cipher algorithms which have the block size of 16 bytes. The third argument @var{flags} can either be passed as @code{0} or as @@ -3548,6 +3554,30 @@ block cipher algorithm. This is GMAC message authentication algorithm based on the SEED block cipher algorithm. + at item GCRY_MAC_POLY1305 +This is plain Poly1305 message authentication algorithm, used with +one-time key. + + at item GCRY_MAC_POLY1305_AES +This is Poly1305-AES message authentication algorithm, used with +key and one-time nonce. + + at item GCRY_MAC_POLY1305_CAMELLIA +This is Poly1305-Camellia message authentication algorithm, used with +key and one-time nonce. + + at item GCRY_MAC_POLY1305_TWOFISH +This is Poly1305-Twofish message authentication algorithm, used with +key and one-time nonce. + + at item GCRY_MAC_POLY1305_SERPENT +This is Poly1305-Serpent message authentication algorithm, used with +key and one-time nonce. + + at item GCRY_MAC_POLY1305_SEED +This is Poly1305-SEED message authentication algorithm, used with +key and one-time nonce. + @end table @c end table of MAC algorithms @@ -3593,8 +3623,8 @@ underlying block cipher. @end deftypefun -GMAC algorithms need initialization vector to be set, which can be -performed with function: +GMAC algorithms and Poly1305-with-cipher algorithms need initialization vector to be set, +which can be performed with function: @deftypefun gcry_error_t gcry_mac_setiv (gcry_mac_hd_t @var{h}, const void *@var{iv}, size_t @var{ivlen}) commit 323b1eb80ff3396d83fedbe5bba9a4e6c412d192 Author: Jussi Kivilinna Date: Fri May 16 21:28:26 2014 +0300 chacha20: add SSE2/AMD64 optimized implementation * cipher/Makefile.am: Add 'chacha20-sse2-amd64.S'. * cipher/chacha20-sse2-amd64.S: New. * cipher/chacha20.c (USE_SSE2): New. [USE_SSE2] (_gcry_chacha20_amd64_sse2_blocks): New. (chacha20_do_setkey) [USE_SSE2]: Use SSE2 implementation for blocks function. * configure.ac [host=x86-64]: Add 'chacha20-sse2-amd64.lo'. -- Add Andrew Moon's public domain SSE2 implementation of ChaCha20. Original source is available at: https://github.com/floodyberry/chacha-opt Benchmark on Intel i5-4570 (haswell), with "--disable-hwf intel-avx2 --disable-hwf intel-ssse3": Old: CHACHA20 | nanosecs/byte mebibytes/sec cycles/byte STREAM enc | 1.97 ns/B 483.8 MiB/s 6.31 c/B STREAM dec | 1.97 ns/B 483.6 MiB/s 6.31 c/B New: CHACHA20 | nanosecs/byte mebibytes/sec cycles/byte STREAM enc | 0.931 ns/B 1024.7 MiB/s 2.98 c/B STREAM dec | 0.930 ns/B 1025.0 MiB/s 2.98 c/B Signed-off-by: Jussi Kivilinna diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 19b0097..8a3bd19 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -60,7 +60,7 @@ EXTRA_libcipher_la_SOURCES = \ arcfour.c arcfour-amd64.S \ blowfish.c blowfish-amd64.S blowfish-arm.S \ cast5.c cast5-amd64.S cast5-arm.S \ -chacha20.c chacha20-ssse3-amd64.S chacha20-avx2-amd64.S \ +chacha20.c chacha20-sse2-amd64.S chacha20-ssse3-amd64.S chacha20-avx2-amd64.S \ crc.c \ des.c des-amd64.S \ dsa.c \ diff --git a/cipher/chacha20-sse2-amd64.S b/cipher/chacha20-sse2-amd64.S new file mode 100644 index 0000000..4811f40 --- /dev/null +++ b/cipher/chacha20-sse2-amd64.S @@ -0,0 +1,652 @@ +/* chacha20-sse2-amd64.S - AMD64/SSE2 implementation of ChaCha20 + * + * Copyright (C) 2014 Jussi Kivilinna + * + * 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, see . + */ + +/* + * Based on public domain implementation by Andrew Moon at + * https://github.com/floodyberry/chacha-opt + */ + +#ifdef __x86_64__ +#include + +#if defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) && USE_CHACHA20 + +.text + +.align 8 +.globl _gcry_chacha20_amd64_sse2_blocks +.type _gcry_chacha20_amd64_sse2_blocks, at function; +_gcry_chacha20_amd64_sse2_blocks: +.Lchacha_blocks_sse2_local: + pushq %rbx + pushq %rbp + movq %rsp, %rbp + andq $~63, %rsp + subq $512, %rsp + movdqu (%rdi), %xmm8 + movdqu 16(%rdi), %xmm9 + movdqu 32(%rdi), %xmm10 + movdqu 48(%rdi), %xmm11 + movq $20, %rax + movq $1, %r9 + movdqa %xmm8, 0(%rsp) + movdqa %xmm9, 16(%rsp) + movdqa %xmm10, 32(%rsp) + movdqa %xmm11, 48(%rsp) + movq %rax, 64(%rsp) + cmpq $256, %rcx + jb .Lchacha_blocks_sse2_below256 + pshufd $0x00, %xmm8, %xmm0 + pshufd $0x55, %xmm8, %xmm1 + pshufd $0xaa, %xmm8, %xmm2 + pshufd $0xff, %xmm8, %xmm3 + movdqa %xmm0, 128(%rsp) + movdqa %xmm1, 144(%rsp) + movdqa %xmm2, 160(%rsp) + movdqa %xmm3, 176(%rsp) + pshufd $0x00, %xmm9, %xmm0 + pshufd $0x55, %xmm9, %xmm1 + pshufd $0xaa, %xmm9, %xmm2 + pshufd $0xff, %xmm9, %xmm3 + movdqa %xmm0, 192(%rsp) + movdqa %xmm1, 208(%rsp) + movdqa %xmm2, 224(%rsp) + movdqa %xmm3, 240(%rsp) + pshufd $0x00, %xmm10, %xmm0 + pshufd $0x55, %xmm10, %xmm1 + pshufd $0xaa, %xmm10, %xmm2 + pshufd $0xff, %xmm10, %xmm3 + movdqa %xmm0, 256(%rsp) + movdqa %xmm1, 272(%rsp) + movdqa %xmm2, 288(%rsp) + movdqa %xmm3, 304(%rsp) + pshufd $0xaa, %xmm11, %xmm0 + pshufd $0xff, %xmm11, %xmm1 + movdqa %xmm0, 352(%rsp) + movdqa %xmm1, 368(%rsp) + jmp .Lchacha_blocks_sse2_atleast256 +.p2align 6,,63 +.Lchacha_blocks_sse2_atleast256: + movq 48(%rsp), %rax + leaq 1(%rax), %r8 + leaq 2(%rax), %r9 + leaq 3(%rax), %r10 + leaq 4(%rax), %rbx + movl %eax, 320(%rsp) + movl %r8d, 4+320(%rsp) + movl %r9d, 8+320(%rsp) + movl %r10d, 12+320(%rsp) + shrq $32, %rax + shrq $32, %r8 + shrq $32, %r9 + shrq $32, %r10 + movl %eax, 336(%rsp) + movl %r8d, 4+336(%rsp) + movl %r9d, 8+336(%rsp) + movl %r10d, 12+336(%rsp) + movq %rbx, 48(%rsp) + movq 64(%rsp), %rax + movdqa 128(%rsp), %xmm0 + movdqa 144(%rsp), %xmm1 + movdqa 160(%rsp), %xmm2 + movdqa 176(%rsp), %xmm3 + movdqa 192(%rsp), %xmm4 + movdqa 208(%rsp), %xmm5 + movdqa 224(%rsp), %xmm6 + movdqa 240(%rsp), %xmm7 + movdqa 256(%rsp), %xmm8 + movdqa 272(%rsp), %xmm9 + movdqa 288(%rsp), %xmm10 + movdqa 304(%rsp), %xmm11 + movdqa 320(%rsp), %xmm12 + movdqa 336(%rsp), %xmm13 + movdqa 352(%rsp), %xmm14 + movdqa 368(%rsp), %xmm15 +.Lchacha_blocks_sse2_mainloop1: + paddd %xmm4, %xmm0 + paddd %xmm5, %xmm1 + pxor %xmm0, %xmm12 + pxor %xmm1, %xmm13 + paddd %xmm6, %xmm2 + paddd %xmm7, %xmm3 + movdqa %xmm6, 96(%rsp) + pxor %xmm2, %xmm14 + pxor %xmm3, %xmm15 + pshuflw $0xb1,%xmm12,%xmm12 + pshufhw $0xb1,%xmm12,%xmm12 + pshuflw $0xb1,%xmm13,%xmm13 + pshufhw $0xb1,%xmm13,%xmm13 + pshuflw $0xb1,%xmm14,%xmm14 + pshufhw $0xb1,%xmm14,%xmm14 + pshuflw $0xb1,%xmm15,%xmm15 + pshufhw $0xb1,%xmm15,%xmm15 + paddd %xmm12, %xmm8 + paddd %xmm13, %xmm9 + paddd %xmm14, %xmm10 + paddd %xmm15, %xmm11 + movdqa %xmm12, 112(%rsp) + pxor %xmm8, %xmm4 + pxor %xmm9, %xmm5 + movdqa 96(%rsp), %xmm6 + movdqa %xmm4, %xmm12 + pslld $ 12, %xmm4 + psrld $20, %xmm12 + pxor %xmm12, %xmm4 + movdqa %xmm5, %xmm12 + pslld $ 12, %xmm5 + psrld $20, %xmm12 + pxor %xmm12, %xmm5 + pxor %xmm10, %xmm6 + pxor %xmm11, %xmm7 + movdqa %xmm6, %xmm12 + pslld $ 12, %xmm6 + psrld $20, %xmm12 + pxor %xmm12, %xmm6 + movdqa %xmm7, %xmm12 + pslld $ 12, %xmm7 + psrld $20, %xmm12 + pxor %xmm12, %xmm7 + movdqa 112(%rsp), %xmm12 + paddd %xmm4, %xmm0 + paddd %xmm5, %xmm1 + pxor %xmm0, %xmm12 + pxor %xmm1, %xmm13 + paddd %xmm6, %xmm2 + paddd %xmm7, %xmm3 + movdqa %xmm6, 96(%rsp) + pxor %xmm2, %xmm14 + pxor %xmm3, %xmm15 + movdqa %xmm12, %xmm6 + pslld $ 8, %xmm12 + psrld $24, %xmm6 + pxor %xmm6, %xmm12 + movdqa %xmm13, %xmm6 + pslld $ 8, %xmm13 + psrld $24, %xmm6 + pxor %xmm6, %xmm13 + paddd %xmm12, %xmm8 + paddd %xmm13, %xmm9 + movdqa %xmm14, %xmm6 + pslld $ 8, %xmm14 + psrld $24, %xmm6 + pxor %xmm6, %xmm14 + movdqa %xmm15, %xmm6 + pslld $ 8, %xmm15 + psrld $24, %xmm6 + pxor %xmm6, %xmm15 + paddd %xmm14, %xmm10 + paddd %xmm15, %xmm11 + movdqa %xmm12, 112(%rsp) + pxor %xmm8, %xmm4 + pxor %xmm9, %xmm5 + movdqa 96(%rsp), %xmm6 + movdqa %xmm4, %xmm12 + pslld $ 7, %xmm4 + psrld $25, %xmm12 + pxor %xmm12, %xmm4 + movdqa %xmm5, %xmm12 + pslld $ 7, %xmm5 + psrld $25, %xmm12 + pxor %xmm12, %xmm5 + pxor %xmm10, %xmm6 + pxor %xmm11, %xmm7 + movdqa %xmm6, %xmm12 + pslld $ 7, %xmm6 + psrld $25, %xmm12 + pxor %xmm12, %xmm6 + movdqa %xmm7, %xmm12 + pslld $ 7, %xmm7 + psrld $25, %xmm12 + pxor %xmm12, %xmm7 + movdqa 112(%rsp), %xmm12 + paddd %xmm5, %xmm0 + paddd %xmm6, %xmm1 + pxor %xmm0, %xmm15 + pxor %xmm1, %xmm12 + paddd %xmm7, %xmm2 + paddd %xmm4, %xmm3 + movdqa %xmm7, 96(%rsp) + pxor %xmm2, %xmm13 + pxor %xmm3, %xmm14 + pshuflw $0xb1,%xmm15,%xmm15 + pshufhw $0xb1,%xmm15,%xmm15 + pshuflw $0xb1,%xmm12,%xmm12 + pshufhw $0xb1,%xmm12,%xmm12 + pshuflw $0xb1,%xmm13,%xmm13 + pshufhw $0xb1,%xmm13,%xmm13 + pshuflw $0xb1,%xmm14,%xmm14 + pshufhw $0xb1,%xmm14,%xmm14 + paddd %xmm15, %xmm10 + paddd %xmm12, %xmm11 + paddd %xmm13, %xmm8 + paddd %xmm14, %xmm9 + movdqa %xmm15, 112(%rsp) + pxor %xmm10, %xmm5 + pxor %xmm11, %xmm6 + movdqa 96(%rsp), %xmm7 + movdqa %xmm5, %xmm15 + pslld $ 12, %xmm5 + psrld $20, %xmm15 + pxor %xmm15, %xmm5 + movdqa %xmm6, %xmm15 + pslld $ 12, %xmm6 + psrld $20, %xmm15 + pxor %xmm15, %xmm6 + pxor %xmm8, %xmm7 + pxor %xmm9, %xmm4 + movdqa %xmm7, %xmm15 + pslld $ 12, %xmm7 + psrld $20, %xmm15 + pxor %xmm15, %xmm7 + movdqa %xmm4, %xmm15 + pslld $ 12, %xmm4 + psrld $20, %xmm15 + pxor %xmm15, %xmm4 + movdqa 112(%rsp), %xmm15 + paddd %xmm5, %xmm0 + paddd %xmm6, %xmm1 + pxor %xmm0, %xmm15 + pxor %xmm1, %xmm12 + paddd %xmm7, %xmm2 + paddd %xmm4, %xmm3 + movdqa %xmm7, 96(%rsp) + pxor %xmm2, %xmm13 + pxor %xmm3, %xmm14 + movdqa %xmm15, %xmm7 + pslld $ 8, %xmm15 + psrld $24, %xmm7 + pxor %xmm7, %xmm15 + movdqa %xmm12, %xmm7 + pslld $ 8, %xmm12 + psrld $24, %xmm7 + pxor %xmm7, %xmm12 + paddd %xmm15, %xmm10 + paddd %xmm12, %xmm11 + movdqa %xmm13, %xmm7 + pslld $ 8, %xmm13 + psrld $24, %xmm7 + pxor %xmm7, %xmm13 + movdqa %xmm14, %xmm7 + pslld $ 8, %xmm14 + psrld $24, %xmm7 + pxor %xmm7, %xmm14 + paddd %xmm13, %xmm8 + paddd %xmm14, %xmm9 + movdqa %xmm15, 112(%rsp) + pxor %xmm10, %xmm5 + pxor %xmm11, %xmm6 + movdqa 96(%rsp), %xmm7 + movdqa %xmm5, %xmm15 + pslld $ 7, %xmm5 + psrld $25, %xmm15 + pxor %xmm15, %xmm5 + movdqa %xmm6, %xmm15 + pslld $ 7, %xmm6 + psrld $25, %xmm15 + pxor %xmm15, %xmm6 + pxor %xmm8, %xmm7 + pxor %xmm9, %xmm4 + movdqa %xmm7, %xmm15 + pslld $ 7, %xmm7 + psrld $25, %xmm15 + pxor %xmm15, %xmm7 + movdqa %xmm4, %xmm15 + pslld $ 7, %xmm4 + psrld $25, %xmm15 + pxor %xmm15, %xmm4 + movdqa 112(%rsp), %xmm15 + subq $2, %rax + jnz .Lchacha_blocks_sse2_mainloop1 + paddd 128(%rsp), %xmm0 + paddd 144(%rsp), %xmm1 + paddd 160(%rsp), %xmm2 + paddd 176(%rsp), %xmm3 + paddd 192(%rsp), %xmm4 + paddd 208(%rsp), %xmm5 + paddd 224(%rsp), %xmm6 + paddd 240(%rsp), %xmm7 + paddd 256(%rsp), %xmm8 + paddd 272(%rsp), %xmm9 + paddd 288(%rsp), %xmm10 + paddd 304(%rsp), %xmm11 + paddd 320(%rsp), %xmm12 + paddd 336(%rsp), %xmm13 + paddd 352(%rsp), %xmm14 + paddd 368(%rsp), %xmm15 + movdqa %xmm8, 384(%rsp) + movdqa %xmm9, 400(%rsp) + movdqa %xmm10, 416(%rsp) + movdqa %xmm11, 432(%rsp) + movdqa %xmm12, 448(%rsp) + movdqa %xmm13, 464(%rsp) + movdqa %xmm14, 480(%rsp) + movdqa %xmm15, 496(%rsp) + movdqa %xmm0, %xmm8 + movdqa %xmm2, %xmm9 + movdqa %xmm4, %xmm10 + movdqa %xmm6, %xmm11 + punpckhdq %xmm1, %xmm0 + punpckhdq %xmm3, %xmm2 + punpckhdq %xmm5, %xmm4 + punpckhdq %xmm7, %xmm6 + punpckldq %xmm1, %xmm8 + punpckldq %xmm3, %xmm9 + punpckldq %xmm5, %xmm10 + punpckldq %xmm7, %xmm11 + movdqa %xmm0, %xmm1 + movdqa %xmm4, %xmm3 + movdqa %xmm8, %xmm5 + movdqa %xmm10, %xmm7 + punpckhqdq %xmm2, %xmm0 + punpckhqdq %xmm6, %xmm4 + punpckhqdq %xmm9, %xmm8 + punpckhqdq %xmm11, %xmm10 + punpcklqdq %xmm2, %xmm1 + punpcklqdq %xmm6, %xmm3 + punpcklqdq %xmm9, %xmm5 + punpcklqdq %xmm11, %xmm7 + andq %rsi, %rsi + jz .Lchacha_blocks_sse2_noinput1 + movdqu 0(%rsi), %xmm2 + movdqu 16(%rsi), %xmm6 + movdqu 64(%rsi), %xmm9 + movdqu 80(%rsi), %xmm11 + movdqu 128(%rsi), %xmm12 + movdqu 144(%rsi), %xmm13 + movdqu 192(%rsi), %xmm14 + movdqu 208(%rsi), %xmm15 + pxor %xmm2, %xmm5 + pxor %xmm6, %xmm7 + pxor %xmm9, %xmm8 + pxor %xmm11, %xmm10 + pxor %xmm12, %xmm1 + pxor %xmm13, %xmm3 + pxor %xmm14, %xmm0 + pxor %xmm15, %xmm4 + movdqu %xmm5, 0(%rdx) + movdqu %xmm7, 16(%rdx) + movdqu %xmm8, 64(%rdx) + movdqu %xmm10, 80(%rdx) + movdqu %xmm1, 128(%rdx) + movdqu %xmm3, 144(%rdx) + movdqu %xmm0, 192(%rdx) + movdqu %xmm4, 208(%rdx) + movdqa 384(%rsp), %xmm0 + movdqa 400(%rsp), %xmm1 + movdqa 416(%rsp), %xmm2 + movdqa 432(%rsp), %xmm3 + movdqa 448(%rsp), %xmm4 + movdqa 464(%rsp), %xmm5 + movdqa 480(%rsp), %xmm6 + movdqa 496(%rsp), %xmm7 + movdqa %xmm0, %xmm8 + movdqa %xmm2, %xmm9 + movdqa %xmm4, %xmm10 + movdqa %xmm6, %xmm11 + punpckldq %xmm1, %xmm8 + punpckldq %xmm3, %xmm9 + punpckhdq %xmm1, %xmm0 + punpckhdq %xmm3, %xmm2 + punpckldq %xmm5, %xmm10 + punpckldq %xmm7, %xmm11 + punpckhdq %xmm5, %xmm4 + punpckhdq %xmm7, %xmm6 + movdqa %xmm8, %xmm1 + movdqa %xmm0, %xmm3 + movdqa %xmm10, %xmm5 + movdqa %xmm4, %xmm7 + punpcklqdq %xmm9, %xmm1 + punpcklqdq %xmm11, %xmm5 + punpckhqdq %xmm9, %xmm8 + punpckhqdq %xmm11, %xmm10 + punpcklqdq %xmm2, %xmm3 + punpcklqdq %xmm6, %xmm7 + punpckhqdq %xmm2, %xmm0 + punpckhqdq %xmm6, %xmm4 + movdqu 32(%rsi), %xmm2 + movdqu 48(%rsi), %xmm6 + movdqu 96(%rsi), %xmm9 + movdqu 112(%rsi), %xmm11 + movdqu 160(%rsi), %xmm12 + movdqu 176(%rsi), %xmm13 + movdqu 224(%rsi), %xmm14 + movdqu 240(%rsi), %xmm15 + pxor %xmm2, %xmm1 + pxor %xmm6, %xmm5 + pxor %xmm9, %xmm8 + pxor %xmm11, %xmm10 + pxor %xmm12, %xmm3 + pxor %xmm13, %xmm7 + pxor %xmm14, %xmm0 + pxor %xmm15, %xmm4 + movdqu %xmm1, 32(%rdx) + movdqu %xmm5, 48(%rdx) + movdqu %xmm8, 96(%rdx) + movdqu %xmm10, 112(%rdx) + movdqu %xmm3, 160(%rdx) + movdqu %xmm7, 176(%rdx) + movdqu %xmm0, 224(%rdx) + movdqu %xmm4, 240(%rdx) + addq $256, %rsi + jmp .Lchacha_blocks_sse2_mainloop_cont +.Lchacha_blocks_sse2_noinput1: + movdqu %xmm5, 0(%rdx) + movdqu %xmm7, 16(%rdx) + movdqu %xmm8, 64(%rdx) + movdqu %xmm10, 80(%rdx) + movdqu %xmm1, 128(%rdx) + movdqu %xmm3, 144(%rdx) + movdqu %xmm0, 192(%rdx) + movdqu %xmm4, 208(%rdx) + movdqa 384(%rsp), %xmm0 + movdqa 400(%rsp), %xmm1 + movdqa 416(%rsp), %xmm2 + movdqa 432(%rsp), %xmm3 + movdqa 448(%rsp), %xmm4 + movdqa 464(%rsp), %xmm5 + movdqa 480(%rsp), %xmm6 + movdqa 496(%rsp), %xmm7 + movdqa %xmm0, %xmm8 + movdqa %xmm2, %xmm9 + movdqa %xmm4, %xmm10 + movdqa %xmm6, %xmm11 + punpckldq %xmm1, %xmm8 + punpckldq %xmm3, %xmm9 + punpckhdq %xmm1, %xmm0 + punpckhdq %xmm3, %xmm2 + punpckldq %xmm5, %xmm10 + punpckldq %xmm7, %xmm11 + punpckhdq %xmm5, %xmm4 + punpckhdq %xmm7, %xmm6 + movdqa %xmm8, %xmm1 + movdqa %xmm0, %xmm3 + movdqa %xmm10, %xmm5 + movdqa %xmm4, %xmm7 + punpcklqdq %xmm9, %xmm1 + punpcklqdq %xmm11, %xmm5 + punpckhqdq %xmm9, %xmm8 + punpckhqdq %xmm11, %xmm10 + punpcklqdq %xmm2, %xmm3 + punpcklqdq %xmm6, %xmm7 + punpckhqdq %xmm2, %xmm0 + punpckhqdq %xmm6, %xmm4 + movdqu %xmm1, 32(%rdx) + movdqu %xmm5, 48(%rdx) + movdqu %xmm8, 96(%rdx) + movdqu %xmm10, 112(%rdx) + movdqu %xmm3, 160(%rdx) + movdqu %xmm7, 176(%rdx) + movdqu %xmm0, 224(%rdx) + movdqu %xmm4, 240(%rdx) +.Lchacha_blocks_sse2_mainloop_cont: + addq $256, %rdx + subq $256, %rcx + cmp $256, %rcx + jae .Lchacha_blocks_sse2_atleast256 + movdqa 0(%rsp), %xmm8 + movdqa 16(%rsp), %xmm9 + movdqa 32(%rsp), %xmm10 + movdqa 48(%rsp), %xmm11 + movq $1, %r9 +.Lchacha_blocks_sse2_below256: + movq %r9, %xmm5 + andq %rcx, %rcx + jz .Lchacha_blocks_sse2_done + cmpq $64, %rcx + jae .Lchacha_blocks_sse2_above63 + movq %rdx, %r9 + andq %rsi, %rsi + jz .Lchacha_blocks_sse2_noinput2 + movq %rcx, %r10 + movq %rsp, %rdx + addq %r10, %rsi + addq %r10, %rdx + negq %r10 +.Lchacha_blocks_sse2_copyinput: + movb (%rsi, %r10), %al + movb %al, (%rdx, %r10) + incq %r10 + jnz .Lchacha_blocks_sse2_copyinput + movq %rsp, %rsi +.Lchacha_blocks_sse2_noinput2: + movq %rsp, %rdx +.Lchacha_blocks_sse2_above63: + movdqa %xmm8, %xmm0 + movdqa %xmm9, %xmm1 + movdqa %xmm10, %xmm2 + movdqa %xmm11, %xmm3 + movq 64(%rsp), %rax +.Lchacha_blocks_sse2_mainloop2: + paddd %xmm1, %xmm0 + pxor %xmm0, %xmm3 + pshuflw $0xb1,%xmm3,%xmm3 + pshufhw $0xb1,%xmm3,%xmm3 + paddd %xmm3, %xmm2 + pxor %xmm2, %xmm1 + movdqa %xmm1,%xmm4 + pslld $12, %xmm1 + psrld $20, %xmm4 + pxor %xmm4, %xmm1 + paddd %xmm1, %xmm0 + pxor %xmm0, %xmm3 + movdqa %xmm3,%xmm4 + pslld $8, %xmm3 + psrld $24, %xmm4 + pshufd $0x93,%xmm0,%xmm0 + pxor %xmm4, %xmm3 + paddd %xmm3, %xmm2 + pshufd $0x4e,%xmm3,%xmm3 + pxor %xmm2, %xmm1 + pshufd $0x39,%xmm2,%xmm2 + movdqa %xmm1,%xmm4 + pslld $7, %xmm1 + psrld $25, %xmm4 + pxor %xmm4, %xmm1 + subq $2, %rax + paddd %xmm1, %xmm0 + pxor %xmm0, %xmm3 + pshuflw $0xb1,%xmm3,%xmm3 + pshufhw $0xb1,%xmm3,%xmm3 + paddd %xmm3, %xmm2 + pxor %xmm2, %xmm1 + movdqa %xmm1,%xmm4 + pslld $12, %xmm1 + psrld $20, %xmm4 + pxor %xmm4, %xmm1 + paddd %xmm1, %xmm0 + pxor %xmm0, %xmm3 + movdqa %xmm3,%xmm4 + pslld $8, %xmm3 + psrld $24, %xmm4 + pshufd $0x39,%xmm0,%xmm0 + pxor %xmm4, %xmm3 + paddd %xmm3, %xmm2 + pshufd $0x4e,%xmm3,%xmm3 + pxor %xmm2, %xmm1 + pshufd $0x93,%xmm2,%xmm2 + movdqa %xmm1,%xmm4 + pslld $7, %xmm1 + psrld $25, %xmm4 + pxor %xmm4, %xmm1 + jnz .Lchacha_blocks_sse2_mainloop2 + paddd %xmm8, %xmm0 + paddd %xmm9, %xmm1 + paddd %xmm10, %xmm2 + paddd %xmm11, %xmm3 + andq %rsi, %rsi + jz .Lchacha_blocks_sse2_noinput3 + movdqu 0(%rsi), %xmm12 + movdqu 16(%rsi), %xmm13 + movdqu 32(%rsi), %xmm14 + movdqu 48(%rsi), %xmm15 + pxor %xmm12, %xmm0 + pxor %xmm13, %xmm1 + pxor %xmm14, %xmm2 + pxor %xmm15, %xmm3 + addq $64, %rsi +.Lchacha_blocks_sse2_noinput3: + movdqu %xmm0, 0(%rdx) + movdqu %xmm1, 16(%rdx) + movdqu %xmm2, 32(%rdx) + movdqu %xmm3, 48(%rdx) + paddq %xmm5, %xmm11 + cmpq $64, %rcx + jbe .Lchacha_blocks_sse2_mainloop2_finishup + addq $64, %rdx + subq $64, %rcx + jmp .Lchacha_blocks_sse2_below256 +.Lchacha_blocks_sse2_mainloop2_finishup: + cmpq $64, %rcx + je .Lchacha_blocks_sse2_done + addq %rcx, %r9 + addq %rcx, %rdx + negq %rcx +.Lchacha_blocks_sse2_copyoutput: + movb (%rdx, %rcx), %al + movb %al, (%r9, %rcx) + incq %rcx + jnz .Lchacha_blocks_sse2_copyoutput +.Lchacha_blocks_sse2_done: + movdqu %xmm11, 48(%rdi) + movq %rbp, %rsp + pxor %xmm15, %xmm15 + pxor %xmm7, %xmm7 + pxor %xmm14, %xmm14 + pxor %xmm6, %xmm6 + pxor %xmm13, %xmm13 + pxor %xmm5, %xmm5 + pxor %xmm12, %xmm12 + pxor %xmm4, %xmm4 + popq %rbp + popq %rbx + movl $(63 + 512 + 16), %eax + pxor %xmm11, %xmm11 + pxor %xmm3, %xmm3 + pxor %xmm10, %xmm10 + pxor %xmm2, %xmm2 + pxor %xmm9, %xmm9 + pxor %xmm1, %xmm1 + pxor %xmm8, %xmm8 + pxor %xmm0, %xmm0 + ret +.size _gcry_chacha20_amd64_sse2_blocks,.-_gcry_chacha20_amd64_sse2_blocks; + +#endif /*defined(USE_CHACHA20)*/ +#endif /*__x86_64*/ diff --git a/cipher/chacha20.c b/cipher/chacha20.c index e2cf442..03416d4 100644 --- a/cipher/chacha20.c +++ b/cipher/chacha20.c @@ -47,6 +47,12 @@ #define CHACHA20_MAX_IV_SIZE 12 /* Bytes. */ #define CHACHA20_INPUT_LENGTH (CHACHA20_BLOCK_SIZE / 4) +/* USE_SSE2 indicates whether to compile with Intel SSE2 code. */ +#undef USE_SSE2 +#if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) +# define USE_SSE2 1 +#endif + /* USE_SSSE3 indicates whether to compile with Intel SSSE3 code. */ #undef USE_SSSE3 #if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) && \ @@ -77,6 +83,13 @@ typedef struct CHACHA20_context_s } CHACHA20_context_t; +#ifdef USE_SSE2 + +unsigned int _gcry_chacha20_amd64_sse2_blocks(u32 *state, const byte *in, + byte *out, size_t bytes); + +#endif /* USE_SSE2 */ + #ifdef USE_SSSE3 unsigned int _gcry_chacha20_amd64_ssse3_blocks(u32 *state, const byte *in, @@ -323,7 +336,12 @@ chacha20_do_setkey (CHACHA20_context_t * ctx, if (keylen != CHACHA20_MAX_KEY_SIZE && keylen != CHACHA20_MIN_KEY_SIZE) return GPG_ERR_INV_KEYLEN; +#ifdef USE_SSE2 + ctx->blocks = _gcry_chacha20_amd64_sse2_blocks; +#else ctx->blocks = chacha20_blocks; +#endif + #ifdef USE_SSSE3 if (features & HWF_INTEL_SSSE3) ctx->blocks = _gcry_chacha20_amd64_ssse3_blocks; diff --git a/configure.ac b/configure.ac index 47a322b..c5952c7 100644 --- a/configure.ac +++ b/configure.ac @@ -1815,6 +1815,7 @@ if test "$found" = "1" ; then case "${host}" in x86_64-*-*) # Build with the assembly implementation + GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-sse2-amd64.lo" GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-ssse3-amd64.lo" GCRYPT_CIPHERS="$GCRYPT_CIPHERS chacha20-avx2-amd64.lo" ;; commit 98f021961ee65669037bc8bb552a69fd78f610fc Author: Jussi Kivilinna Date: Sun May 11 20:52:27 2014 +0300 poly1305: add AMD64/AVX2 optimized implementation * cipher/Makefile.am: Add 'poly1305-avx2-amd64.S'. * cipher/poly1305-avx2-amd64.S: New. * cipher/poly1305-internal.h (POLY1305_USE_AVX2) (POLY1305_AVX2_BLOCKSIZE, POLY1305_AVX2_STATESIZE) (POLY1305_AVX2_ALIGNMENT): New. (POLY1305_LARGEST_BLOCKSIZE, POLY1305_LARGEST_STATESIZE) (POLY1305_STATE_ALIGNMENT): Use AVX2 versions when needed. * cipher/poly1305.c [POLY1305_USE_AVX2] (_gcry_poly1305_amd64_avx2_init_ext) (_gcry_poly1305_amd64_avx2_finish_ext) (_gcry_poly1305_amd64_avx2_blocks, poly1305_amd64_avx2_ops): New. (_gcry_poly1305_init) [POLY1305_USE_AVX2]: Use AVX2 implementation if AVX2 supported by CPU. * configure.ac [host=x86_64]: Add 'poly1305-avx2-amd64.lo'. -- Add Andrew Moon's public domain AVX2 implementation of Poly1305. Original source is available at: https://github.com/floodyberry/poly1305-opt Benchmarks on Intel i5-4570 (haswell): Old: | nanosecs/byte mebibytes/sec cycles/byte POLY1305 | 0.448 ns/B 2129.5 MiB/s 1.43 c/B New: | nanosecs/byte mebibytes/sec cycles/byte POLY1305 | 0.205 ns/B 4643.5 MiB/s 0.657 c/B Signed-off-by: Jussi Kivilinna diff --git a/cipher/Makefile.am b/cipher/Makefile.am index a32ae89..19b0097 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -72,7 +72,7 @@ gost28147.c gost.h \ gostr3411-94.c \ md4.c \ md5.c \ -poly1305-sse2-amd64.S \ +poly1305-sse2-amd64.S poly1305-avx2-amd64.S \ rijndael.c rijndael-tables.h rijndael-amd64.S rijndael-arm.S \ rmd160.c \ rsa.c \ diff --git a/cipher/poly1305-avx2-amd64.S b/cipher/poly1305-avx2-amd64.S new file mode 100644 index 0000000..0ba7e76 --- /dev/null +++ b/cipher/poly1305-avx2-amd64.S @@ -0,0 +1,954 @@ +/* poly1305-avx2-amd64.S - AMD64/AVX2 implementation of Poly1305 + * + * Copyright (C) 2014 Jussi Kivilinna + * + * 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, see . + */ + +/* + * Based on public domain implementation by Andrew Moon at + * https://github.com/floodyberry/poly1305-opt + */ + +#include + +#if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) && \ + defined(ENABLE_AVX2_SUPPORT) + +.text + + +.align 8 +.globl _gcry_poly1305_amd64_avx2_init_ext +.type _gcry_poly1305_amd64_avx2_init_ext, at function; +_gcry_poly1305_amd64_avx2_init_ext: +.Lpoly1305_init_ext_avx2_local: + xor %edx, %edx + vzeroupper + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + movq %rdx, %rcx + vpxor %ymm0, %ymm0, %ymm0 + movq $-1, %r8 + testq %rcx, %rcx + vmovdqu %ymm0, (%rdi) + vmovdqu %ymm0, 32(%rdi) + vmovdqu %ymm0, 64(%rdi) + vmovdqu %ymm0, 96(%rdi) + vmovdqu %ymm0, 128(%rdi) + movq 8(%rsi), %r9 + cmove %r8, %rcx + movq $0xffc0fffffff, %r8 + movq %r9, %r13 + movq (%rsi), %r10 + andq %r10, %r8 + shrq $44, %r10 + movq %r8, %r14 + shlq $20, %r13 + orq %r13, %r10 + movq $0xfffffc0ffff, %r13 + shrq $24, %r9 + andq %r13, %r10 + movq $0xffffffc0f, %r13 + andq %r13, %r9 + movl %r8d, %r13d + andl $67108863, %r13d + movl %r13d, 164(%rdi) + movq %r10, %r13 + shrq $26, %r14 + shlq $18, %r13 + orq %r13, %r14 + movq %r10, %r13 + shrq $8, %r13 + andl $67108863, %r14d + andl $67108863, %r13d + movl %r14d, 172(%rdi) + movq %r10, %r14 + movl %r13d, 180(%rdi) + movq %r9, %r13 + shrq $34, %r14 + shlq $10, %r13 + orq %r13, %r14 + movq %r9, %r13 + shrq $16, %r13 + andl $67108863, %r14d + movl %r14d, 188(%rdi) + movl %r13d, 196(%rdi) + cmpq $16, %rcx + jbe .Lpoly1305_init_ext_avx2_continue + lea (%r9,%r9,4), %r11 + shlq $2, %r11 + lea (%r10,%r10), %rax + mulq %r11 + movq %rax, %r13 + movq %r8, %rax + movq %rdx, %r14 + mulq %r8 + addq %rax, %r13 + lea (%r8,%r8), %rax + movq %r13, %r12 + adcq %rdx, %r14 + mulq %r10 + shlq $20, %r14 + movq %rax, %r15 + shrq $44, %r12 + movq %r11, %rax + orq %r12, %r14 + movq %rdx, %r12 + mulq %r9 + addq %rax, %r15 + movq %r8, %rax + adcq %rdx, %r12 + addq %r15, %r14 + lea (%r9,%r9), %r15 + movq %r14, %rbx + adcq $0, %r12 + mulq %r15 + shlq $20, %r12 + movq %rdx, %r11 + shrq $44, %rbx + orq %rbx, %r12 + movq %rax, %rbx + movq %r10, %rax + mulq %r10 + addq %rax, %rbx + adcq %rdx, %r11 + addq %rbx, %r12 + movq $0xfffffffffff, %rbx + movq %r12, %r15 + adcq $0, %r11 + andq %rbx, %r13 + shlq $22, %r11 + andq %rbx, %r14 + shrq $42, %r15 + orq %r15, %r11 + lea (%r11,%r11,4), %r11 + addq %r11, %r13 + movq %rbx, %r11 + andq %r13, %r11 + shrq $44, %r13 + movq %r11, %r15 + addq %r13, %r14 + movq $0x3ffffffffff, %r13 + andq %r14, %rbx + andq %r13, %r12 + movq %rbx, %r13 + shrq $26, %r15 + shlq $18, %r13 + orq %r13, %r15 + movq %rbx, %r13 + shrq $44, %r14 + shrq $8, %r13 + addq %r14, %r12 + movl %r11d, %r14d + andl $67108863, %r15d + andl $67108863, %r14d + andl $67108863, %r13d + movl %r14d, 204(%rdi) + movq %rbx, %r14 + movl %r13d, 220(%rdi) + movq %r12, %r13 + shrq $34, %r14 + shlq $10, %r13 + orq %r13, %r14 + movq %r12, %r13 + shrq $16, %r13 + andl $67108863, %r14d + movl %r15d, 212(%rdi) + movl %r14d, 228(%rdi) + movl %r13d, 236(%rdi) + cmpq $32, %rcx + jbe .Lpoly1305_init_ext_avx2_continue + movq %r9, %rax + lea (%rbx,%rbx,4), %r14 + shlq $2, %r14 + mulq %r14 + movq %rdi, -32(%rsp) + lea (%r12,%r12,4), %rdi + shlq $2, %rdi + movq %rax, %r14 + movq %r10, %rax + movq %rdx, %r15 + mulq %rdi + movq %rax, %r13 + movq %r11, %rax + movq %rcx, -16(%rsp) + movq %rdx, %rcx + mulq %r8 + addq %rax, %r13 + movq %rdi, %rax + movq %rsi, -24(%rsp) + adcq %rdx, %rcx + addq %r13, %r14 + adcq %rcx, %r15 + movq %r14, %rcx + mulq %r9 + shlq $20, %r15 + movq %rax, %r13 + shrq $44, %rcx + movq %r11, %rax + orq %rcx, %r15 + movq %rdx, %rcx + mulq %r10 + movq %rax, %rsi + movq %rbx, %rax + movq %rdx, %rdi + mulq %r8 + addq %rax, %rsi + movq %r11, %rax + adcq %rdx, %rdi + addq %rsi, %r13 + adcq %rdi, %rcx + addq %r13, %r15 + movq %r15, %rdi + adcq $0, %rcx + mulq %r9 + shlq $20, %rcx + movq %rdx, %rsi + shrq $44, %rdi + orq %rdi, %rcx + movq %rax, %rdi + movq %rbx, %rax + mulq %r10 + movq %rax, %r9 + movq %r8, %rax + movq %rdx, %r10 + movq $0xfffffffffff, %r8 + mulq %r12 + addq %rax, %r9 + adcq %rdx, %r10 + andq %r8, %r14 + addq %r9, %rdi + adcq %r10, %rsi + andq %r8, %r15 + addq %rdi, %rcx + movq $0x3ffffffffff, %rdi + movq %rcx, %r10 + adcq $0, %rsi + andq %rdi, %rcx + shlq $22, %rsi + shrq $42, %r10 + orq %r10, %rsi + movq -32(%rsp), %rdi + lea (%rsi,%rsi,4), %r9 + movq %r8, %rsi + addq %r9, %r14 + andq %r14, %rsi + shrq $44, %r14 + addq %r14, %r15 + andq %r15, %r8 + shrq $44, %r15 + movq %r8, %r14 + addq %r15, %rcx + movl %esi, %r15d + movq %rcx, %r10 + movq %r8, %r9 + shrq $26, %rsi + andl $67108863, %r15d + shlq $18, %r14 + shrq $34, %r8 + orq %r14, %rsi + shlq $10, %r10 + shrq $8, %r9 + orq %r10, %r8 + shrq $16, %rcx + andl $67108863, %esi + movl %esi, 252(%rdi) + andl $67108863, %r9d + movl %ecx, 276(%rdi) + andl $67108863, %r8d + movl %r15d, 244(%rdi) + movl %r9d, 260(%rdi) + movl %r8d, 268(%rdi) + movq -16(%rsp), %rcx + movq -24(%rsp), %rsi +.Lpoly1305_init_ext_avx2_continue: + movl 16(%rsi), %r8d + movl %r8d, 284(%rdi) + movl 20(%rsi), %r9d + movl %r9d, 292(%rdi) + movl 24(%rsi), %r10d + movl %r10d, 300(%rdi) + movl 28(%rsi), %esi + movl %esi, 308(%rdi) + cmpq $48, %rcx + jbe .Lpoly1305_init_ext_avx2_done + lea (%r12,%r12,4), %r9 + shlq $2, %r9 + lea (%rbx,%rbx), %rax + mulq %r9 + movq %rax, %rsi + movq %r11, %rax + movq %rdx, %r8 + mulq %r11 + addq %rax, %rsi + lea (%r11,%r11), %rax + movq %rsi, %r10 + adcq %rdx, %r8 + mulq %rbx + movq %rax, %r13 + movq %r12, %rax + movq %rdx, %rcx + addq %r12, %r12 + mulq %r9 + addq %rax, %r13 + movq %r11, %rax + movq $0xfffffffffff, %r9 + adcq %rdx, %rcx + andq %r9, %rsi + mulq %r12 + shlq $20, %r8 + movq %rax, %r11 + shrq $44, %r10 + movq %rbx, %rax + orq %r10, %r8 + movq %rdx, %r12 + mulq %rbx + addq %r13, %r8 + movq %r8, %r14 + adcq $0, %rcx + andq %r9, %r8 + addq %rax, %r11 + adcq %rdx, %r12 + shlq $20, %rcx + shrq $44, %r14 + orq %r14, %rcx + addq %r11, %rcx + movq %rcx, %rbx + adcq $0, %r12 + shlq $22, %r12 + shrq $42, %rbx + orq %rbx, %r12 + movq %r9, %rbx + lea (%r12,%r12,4), %r15 + addq %r15, %rsi + andq %rsi, %rbx + shrq $44, %rsi + movl %ebx, %r11d + addq %rsi, %r8 + movq $0x3ffffffffff, %rsi + andq %r8, %r9 + andq %rsi, %rcx + shrq $44, %r8 + movq %r9, %rax + addq %r8, %rcx + movq %r9, %r8 + movq %rcx, %r10 + andl $67108863, %r11d + shrq $26, %rbx + shlq $18, %r8 + shrq $34, %r9 + orq %r8, %rbx + shlq $10, %r10 + shrq $8, %rax + orq %r10, %r9 + shrq $16, %rcx + andl $67108863, %ebx + andl $67108863, %eax + andl $67108863, %r9d + movl %r11d, 184(%rdi) + movl %r11d, 176(%rdi) + movl %r11d, 168(%rdi) + movl %r11d, 160(%rdi) + movl %ebx, 216(%rdi) + movl %ebx, 208(%rdi) + movl %ebx, 200(%rdi) + movl %ebx, 192(%rdi) + movl %eax, 248(%rdi) + movl %eax, 240(%rdi) + movl %eax, 232(%rdi) + movl %eax, 224(%rdi) + movl %r9d, 280(%rdi) + movl %r9d, 272(%rdi) + movl %r9d, 264(%rdi) + movl %r9d, 256(%rdi) + movl %ecx, 312(%rdi) + movl %ecx, 304(%rdi) + movl %ecx, 296(%rdi) + movl %ecx, 288(%rdi) +.Lpoly1305_init_ext_avx2_done: + movq $0, 320(%rdi) + vzeroall + popq %rbx + popq %r15 + popq %r14 + popq %r13 + popq %r12 + ret +.size _gcry_poly1305_amd64_avx2_init_ext,.-_gcry_poly1305_amd64_avx2_init_ext; + + +.align 8 +.globl _gcry_poly1305_amd64_avx2_blocks +.type _gcry_poly1305_amd64_avx2_blocks, at function; +_gcry_poly1305_amd64_avx2_blocks: +.Lpoly1305_blocks_avx2_local: + vzeroupper + pushq %rbp + movq %rsp, %rbp + pushq %rbx + andq $-64, %rsp + subq $200, %rsp + movl $((1<<26)-1), %r8d + movl $(5), %r9d + movl $((1<<24)), %r10d + vmovd %r8d, %xmm0 + vmovd %r9d, %xmm8 + vmovd %r10d, %xmm7 + vpbroadcastq %xmm0, %ymm0 + vpbroadcastq %xmm8, %ymm8 + vpbroadcastq %xmm7, %ymm7 + vmovdqa %ymm7, 168(%rsp) + movq 320(%rdi), %rax + testb $60, %al + je .Lpoly1305_blocks_avx2_9 + vmovdqa 168(%rsp), %ymm7 + vpsrldq $8, %ymm7, %ymm1 + vmovdqa %ymm1, 168(%rsp) + testb $4, %al + je .Lpoly1305_blocks_avx2_10 + vpermq $192, %ymm1, %ymm7 + vmovdqa %ymm7, 168(%rsp) +.Lpoly1305_blocks_avx2_10: + testb $8, %al + je .Lpoly1305_blocks_avx2_11 + vpermq $240, 168(%rsp), %ymm7 + vmovdqa %ymm7, 168(%rsp) +.Lpoly1305_blocks_avx2_11: + testb $16, %al + je .Lpoly1305_blocks_avx2_12 + vpermq $252, 168(%rsp), %ymm6 + vmovdqa %ymm6, 168(%rsp) +.Lpoly1305_blocks_avx2_12: + testb $32, %al + je .Lpoly1305_blocks_avx2_9 + vpxor %xmm6, %xmm6, %xmm6 + vmovdqa %ymm6, 168(%rsp) +.Lpoly1305_blocks_avx2_9: + testb $1, %al + jne .Lpoly1305_blocks_avx2_13 + vmovdqu (%rsi), %ymm3 + vmovdqu 32(%rsi), %ymm1 + vpunpcklqdq %ymm1, %ymm3, %ymm2 + vpunpckhqdq %ymm1, %ymm3, %ymm1 + vpermq $216, %ymm2, %ymm2 + vpermq $216, %ymm1, %ymm1 + vpand %ymm2, %ymm0, %ymm5 + vpsrlq $26, %ymm2, %ymm4 + vpand %ymm4, %ymm0, %ymm4 + vpsllq $12, %ymm1, %ymm3 + vpsrlq $52, %ymm2, %ymm2 + vpor %ymm3, %ymm2, %ymm2 + vpand %ymm2, %ymm0, %ymm3 + vpsrlq $26, %ymm2, %ymm2 + vpand %ymm2, %ymm0, %ymm2 + vpsrlq $40, %ymm1, %ymm1 + vpor 168(%rsp), %ymm1, %ymm1 + addq $64, %rsi + subq $64, %rdx + orq $1, 320(%rdi) + jmp .Lpoly1305_blocks_avx2_14 +.Lpoly1305_blocks_avx2_13: + vmovdqa (%rdi), %ymm5 + vmovdqa 32(%rdi), %ymm4 + vmovdqa 64(%rdi), %ymm3 + vmovdqa 96(%rdi), %ymm2 + vmovdqa 128(%rdi), %ymm1 +.Lpoly1305_blocks_avx2_14: + cmpq $63, %rdx + jbe .Lpoly1305_blocks_avx2_15 + vmovdqa 160(%rdi), %ymm6 + vmovdqa %ymm8, 136(%rsp) + vmovdqa 192(%rdi), %ymm7 + vpmuludq %ymm8, %ymm7, %ymm11 + vmovdqa %ymm11, 104(%rsp) + vmovdqa 224(%rdi), %ymm11 + vmovdqa %ymm11, 72(%rsp) + vpmuludq %ymm11, %ymm8, %ymm11 + vmovdqa %ymm11, 40(%rsp) + vmovdqa 256(%rdi), %ymm11 + vmovdqa %ymm11, 8(%rsp) + vpmuludq %ymm11, %ymm8, %ymm11 + vmovdqa %ymm11, -24(%rsp) + vmovdqa 288(%rdi), %ymm13 + vmovdqa %ymm13, -56(%rsp) + vpmuludq %ymm13, %ymm8, %ymm13 + vmovdqa %ymm13, -88(%rsp) +.Lpoly1305_blocks_avx2_16: + vpmuludq 104(%rsp), %ymm1, %ymm14 + vmovdqa 40(%rsp), %ymm13 + vpmuludq %ymm13, %ymm2, %ymm8 + vpmuludq %ymm13, %ymm1, %ymm13 + vmovdqa -24(%rsp), %ymm9 + vpmuludq %ymm9, %ymm2, %ymm10 + vpmuludq %ymm9, %ymm1, %ymm11 + vpaddq %ymm8, %ymm14, %ymm14 + vpmuludq %ymm9, %ymm3, %ymm8 + vmovdqa -88(%rsp), %ymm12 + vpmuludq %ymm12, %ymm1, %ymm9 + vpaddq %ymm10, %ymm13, %ymm13 + vpmuludq %ymm12, %ymm4, %ymm15 + vmovdqa %ymm12, %ymm10 + vpmuludq %ymm12, %ymm3, %ymm12 + vpaddq %ymm8, %ymm14, %ymm14 + vpmuludq %ymm10, %ymm2, %ymm10 + vpmuludq %ymm6, %ymm2, %ymm8 + vpaddq %ymm15, %ymm14, %ymm14 + vpmuludq %ymm6, %ymm1, %ymm1 + vpaddq %ymm12, %ymm13, %ymm13 + vpmuludq %ymm6, %ymm5, %ymm15 + vpaddq %ymm10, %ymm11, %ymm11 + vpmuludq %ymm6, %ymm4, %ymm12 + vpaddq %ymm8, %ymm9, %ymm9 + vpmuludq %ymm6, %ymm3, %ymm10 + vpmuludq %ymm7, %ymm3, %ymm8 + vpaddq %ymm15, %ymm14, %ymm14 + vpmuludq %ymm7, %ymm2, %ymm2 + vpaddq %ymm12, %ymm13, %ymm12 + vpmuludq %ymm7, %ymm5, %ymm15 + vpaddq %ymm10, %ymm11, %ymm10 + vpmuludq %ymm7, %ymm4, %ymm13 + vpaddq %ymm8, %ymm9, %ymm8 + vmovdqa 72(%rsp), %ymm9 + vpmuludq %ymm9, %ymm4, %ymm11 + vpaddq %ymm2, %ymm1, %ymm1 + vpmuludq %ymm9, %ymm3, %ymm3 + vpaddq %ymm15, %ymm12, %ymm12 + vpmuludq %ymm9, %ymm5, %ymm15 + vpaddq %ymm13, %ymm10, %ymm10 + vmovdqa 8(%rsp), %ymm2 + vpmuludq %ymm2, %ymm5, %ymm9 + vpaddq %ymm11, %ymm8, %ymm8 + vpmuludq %ymm2, %ymm4, %ymm4 + vpaddq %ymm3, %ymm1, %ymm1 + vpmuludq -56(%rsp), %ymm5, %ymm5 + vpaddq %ymm15, %ymm10, %ymm10 + vpaddq %ymm9, %ymm8, %ymm8 + vpaddq %ymm4, %ymm1, %ymm1 + vpaddq %ymm5, %ymm1, %ymm5 + vmovdqu (%rsi), %ymm3 + vmovdqu 32(%rsi), %ymm2 + vperm2i128 $32, %ymm2, %ymm3, %ymm1 + vperm2i128 $49, %ymm2, %ymm3, %ymm2 + vpunpckldq %ymm2, %ymm1, %ymm15 + vpunpckhdq %ymm2, %ymm1, %ymm2 + vpxor %xmm4, %xmm4, %xmm4 + vpunpckldq %ymm4, %ymm15, %ymm1 + vpunpckhdq %ymm4, %ymm15, %ymm15 + vpunpckldq %ymm4, %ymm2, %ymm3 + vpunpckhdq %ymm4, %ymm2, %ymm2 + vpsllq $6, %ymm15, %ymm15 + vpsllq $12, %ymm3, %ymm3 + vpsllq $18, %ymm2, %ymm2 + vpaddq %ymm1, %ymm14, %ymm14 + vpaddq %ymm15, %ymm12, %ymm12 + vpaddq %ymm3, %ymm10, %ymm10 + vpaddq %ymm2, %ymm8, %ymm8 + vpaddq 168(%rsp), %ymm5, %ymm5 + addq $64, %rsi + vpsrlq $26, %ymm14, %ymm4 + vpsrlq $26, %ymm8, %ymm2 + vpand %ymm0, %ymm14, %ymm14 + vpand %ymm0, %ymm8, %ymm8 + vpaddq %ymm4, %ymm12, %ymm12 + vpaddq %ymm2, %ymm5, %ymm5 + vpsrlq $26, %ymm12, %ymm3 + vpsrlq $26, %ymm5, %ymm9 + vpand %ymm0, %ymm12, %ymm12 + vpand %ymm0, %ymm5, %ymm11 + vpaddq %ymm3, %ymm10, %ymm3 + vpmuludq 136(%rsp), %ymm9, %ymm9 + vpaddq %ymm9, %ymm14, %ymm14 + vpsrlq $26, %ymm3, %ymm2 + vpsrlq $26, %ymm14, %ymm4 + vpand %ymm0, %ymm3, %ymm3 + vpand %ymm0, %ymm14, %ymm5 + vpaddq %ymm2, %ymm8, %ymm2 + vpaddq %ymm4, %ymm12, %ymm4 + vpsrlq $26, %ymm2, %ymm1 + vpand %ymm0, %ymm2, %ymm2 + vpaddq %ymm1, %ymm11, %ymm1 + subq $64, %rdx + cmpq $63, %rdx + ja .Lpoly1305_blocks_avx2_16 +.Lpoly1305_blocks_avx2_15: + testb $64, 320(%rdi) + jne .Lpoly1305_blocks_avx2_17 + vmovdqa %ymm5, (%rdi) + vmovdqa %ymm4, 32(%rdi) + vmovdqa %ymm3, 64(%rdi) + vmovdqa %ymm2, 96(%rdi) + vmovdqa %ymm1, 128(%rdi) + jmp .Lpoly1305_blocks_avx2_8 +.Lpoly1305_blocks_avx2_17: + vpermq $245, %ymm5, %ymm0 + vpaddq %ymm0, %ymm5, %ymm5 + vpermq $245, %ymm4, %ymm0 + vpaddq %ymm0, %ymm4, %ymm4 + vpermq $245, %ymm3, %ymm0 + vpaddq %ymm0, %ymm3, %ymm3 + vpermq $245, %ymm2, %ymm0 + vpaddq %ymm0, %ymm2, %ymm2 + vpermq $245, %ymm1, %ymm0 + vpaddq %ymm0, %ymm1, %ymm1 + vpermq $170, %ymm5, %ymm0 + vpaddq %ymm0, %ymm5, %ymm5 + vpermq $170, %ymm4, %ymm0 + vpaddq %ymm0, %ymm4, %ymm4 + vpermq $170, %ymm3, %ymm0 + vpaddq %ymm0, %ymm3, %ymm3 + vpermq $170, %ymm2, %ymm0 + vpaddq %ymm0, %ymm2, %ymm2 + vpermq $170, %ymm1, %ymm0 + vpaddq %ymm0, %ymm1, %ymm1 + vmovd %xmm5, %eax + vmovd %xmm4, %edx + movl %eax, %ecx + shrl $26, %ecx + addl %edx, %ecx + movl %ecx, %edx + andl $67108863, %edx + vmovd %xmm3, %esi + shrl $26, %ecx + movl %ecx, %r11d + addl %esi, %r11d + vmovd %xmm2, %ecx + movl %r11d, %r10d + shrl $26, %r10d + addl %ecx, %r10d + movl %r10d, %r9d + andl $67108863, %r9d + vmovd %xmm1, %r8d + movl %edx, %esi + salq $26, %rsi + andl $67108863, %eax + orq %rax, %rsi + movabsq $17592186044415, %rax + andq %rax, %rsi + andl $67108863, %r11d + salq $8, %r11 + shrl $18, %edx + movl %edx, %edx + orq %r11, %rdx + movq %r9, %rcx + salq $34, %rcx + orq %rcx, %rdx + andq %rax, %rdx + shrl $26, %r10d + addl %r10d, %r8d + salq $16, %r8 + shrl $10, %r9d + movl %r9d, %r9d + orq %r9, %r8 + movabsq $4398046511103, %r10 + movq %r8, %r9 + andq %r10, %r9 + shrq $42, %r8 + leaq (%r8,%r8,4), %rcx + addq %rcx, %rsi + movq %rsi, %r8 + andq %rax, %r8 + movq %rsi, %rcx + shrq $44, %rcx + addq %rdx, %rcx + movq %rcx, %rsi + andq %rax, %rsi + shrq $44, %rcx + movq %rcx, %rdx + addq %r9, %rdx + andq %rdx, %r10 + shrq $42, %rdx + leaq (%r8,%rdx,4), %rcx + leaq (%rcx,%rdx), %rdx + movq %rdx, %rbx + andq %rax, %rbx + shrq $44, %rdx + movq %rdx, %r11 + addq %rsi, %r11 + leaq 5(%rbx), %r9 + movq %r9, %r8 + shrq $44, %r8 + addq %r11, %r8 + movabsq $-4398046511104, %rsi + addq %r10, %rsi + movq %r8, %rdx + shrq $44, %rdx + addq %rdx, %rsi + movq %rsi, %rdx + shrq $63, %rdx + subq $1, %rdx + movq %rdx, %rcx + notq %rcx + andq %rcx, %rbx + andq %rcx, %r11 + andq %r10, %rcx + andq %rax, %r9 + andq %rdx, %r9 + orq %r9, %rbx + movq %rbx, (%rdi) + andq %r8, %rax + andq %rdx, %rax + orq %rax, %r11 + movq %r11, 8(%rdi) + andq %rsi, %rdx + orq %rcx, %rdx + movq %rdx, 16(%rdi) +.Lpoly1305_blocks_avx2_8: + movq -8(%rbp), %rbx + vzeroall + movq %rbp, %rax + subq %rsp, %rax + leave + addq $8, %rax + ret +.size _gcry_poly1305_amd64_avx2_blocks,.-_gcry_poly1305_amd64_avx2_blocks; + + +.align 8 +.globl _gcry_poly1305_amd64_avx2_finish_ext +.type _gcry_poly1305_amd64_avx2_finish_ext, at function; +_gcry_poly1305_amd64_avx2_finish_ext: +.Lpoly1305_finish_ext_avx2_local: + vzeroupper + pushq %rbp + movq %rsp, %rbp + pushq %r13 + pushq %r12 + pushq %rbx + andq $-64, %rsp + subq $64, %rsp + movq %rdi, %rbx + movq %rdx, %r13 + movq %rcx, %r12 + testq %rdx, %rdx + je .Lpoly1305_finish_ext_avx2_22 + vpxor %xmm0, %xmm0, %xmm0 + vmovdqa %ymm0, (%rsp) + vmovdqa %ymm0, 32(%rsp) + movq %rsp, %rax + subq %rsp, %rsi + testb $32, %dl + je .Lpoly1305_finish_ext_avx2_23 + vmovdqu (%rsp,%rsi), %ymm0 + vmovdqa %ymm0, (%rsp) + leaq 32(%rsp), %rax +.Lpoly1305_finish_ext_avx2_23: + testb $16, %r13b + je .Lpoly1305_finish_ext_avx2_24 + vmovdqu (%rax,%rsi), %xmm0 + vmovdqa %xmm0, (%rax) + addq $16, %rax +.Lpoly1305_finish_ext_avx2_24: + testb $8, %r13b + je .Lpoly1305_finish_ext_avx2_25 + movq (%rax,%rsi), %rdx + movq %rdx, (%rax) + addq $8, %rax +.Lpoly1305_finish_ext_avx2_25: + testb $4, %r13b + je .Lpoly1305_finish_ext_avx2_26 + movl (%rax,%rsi), %edx + movl %edx, (%rax) + addq $4, %rax +.Lpoly1305_finish_ext_avx2_26: + testb $2, %r13b + je .Lpoly1305_finish_ext_avx2_27 + movzwl (%rax,%rsi), %edx + movw %dx, (%rax) + addq $2, %rax +.Lpoly1305_finish_ext_avx2_27: + testb $1, %r13b + je .Lpoly1305_finish_ext_avx2_28 + movzbl (%rax,%rsi), %edx + movb %dl, (%rax) +.Lpoly1305_finish_ext_avx2_28: + testb $15, %r13b + je .Lpoly1305_finish_ext_avx2_29 + movb $1, (%rsp,%r13) +.Lpoly1305_finish_ext_avx2_29: + cmpq $47, %r13 + jbe .Lpoly1305_finish_ext_avx2_30 + orq $4, 320(%rbx) + jmp .Lpoly1305_finish_ext_avx2_31 +.Lpoly1305_finish_ext_avx2_30: + cmpq $31, %r13 + jbe .Lpoly1305_finish_ext_avx2_32 + orq $8, 320(%rbx) + jmp .Lpoly1305_finish_ext_avx2_31 +.Lpoly1305_finish_ext_avx2_32: + cmpq $15, %r13 + jbe .Lpoly1305_finish_ext_avx2_33 + orq $16, 320(%rbx) + jmp .Lpoly1305_finish_ext_avx2_31 +.Lpoly1305_finish_ext_avx2_33: + orq $32, 320(%rbx) +.Lpoly1305_finish_ext_avx2_31: + testb $1, 320(%rbx) + je .Lpoly1305_finish_ext_avx2_34 + cmpq $32, %r13 + ja .Lpoly1305_finish_ext_avx2_34 + cmpq $17, %r13 + sbbq %rsi, %rsi + notq %rsi + addq $2, %rsi + cmpq $17, %r13 + sbbq %rax, %rax + movq %rbx, %rdx + addq $23, %rax + leaq (%rbx,%rax,8), %rax + movl $0, %ecx +.Lpoly1305_finish_ext_avx2_37: + movl 244(%rdx), %edi + movl %edi, (%rax) + movl 252(%rdx), %edi + movl %edi, 32(%rax) + movl 260(%rdx), %edi + movl %edi, 64(%rax) + movl 268(%rdx), %edi + movl %edi, 96(%rax) + movl 276(%rdx), %edi + movl %edi, 128(%rax) + addq $1, %rcx + subq $40, %rdx + addq $8, %rax + cmpq %rcx, %rsi + ja .Lpoly1305_finish_ext_avx2_37 +.Lpoly1305_finish_ext_avx2_34: + movl $64, %edx + movq %rsp, %rsi + movq %rbx, %rdi + call .Lpoly1305_blocks_avx2_local +.Lpoly1305_finish_ext_avx2_22: + movq 320(%rbx), %r8 + testb $1, %r8b + je .Lpoly1305_finish_ext_avx2_38 + leaq -1(%r13), %rax + cmpq $47, %rax + ja .Lpoly1305_finish_ext_avx2_46 + cmpq $32, %r13 + ja .Lpoly1305_finish_ext_avx2_47 + cmpq $17, %r13 + sbbq %r9, %r9 + addq $2, %r9 + movl $0, %edi + cmpq $17, %r13 + sbbq %rax, %rax + notq %rax + andl $5, %eax + jmp .Lpoly1305_finish_ext_avx2_39 +.Lpoly1305_finish_ext_avx2_41: + movl (%rdx), %esi + movl %esi, (%rax) + movl 8(%rdx), %esi + movl %esi, 32(%rax) + movl 16(%rdx), %esi + movl %esi, 64(%rax) + movl 24(%rdx), %esi + movl %esi, 96(%rax) + movl 32(%rdx), %esi + movl %esi, 128(%rax) + addq $1, %rcx + subq $40, %rdx + addq $8, %rax + movq %rcx, %rsi + subq %rdi, %rsi + cmpq %rsi, %r9 + ja .Lpoly1305_finish_ext_avx2_41 + cmpq $3, %rcx + ja .Lpoly1305_finish_ext_avx2_42 + leaq 160(%rbx,%rcx,8), %rax +.Lpoly1305_finish_ext_avx2_43: + movl $1, (%rax) + movl $0, 32(%rax) + movl $0, 64(%rax) + movl $0, 96(%rax) + movl $0, 128(%rax) + addq $1, %rcx + addq $8, %rax + cmpq $4, %rcx + jne .Lpoly1305_finish_ext_avx2_43 +.Lpoly1305_finish_ext_avx2_42: + orq $96, %r8 + movq %r8, 320(%rbx) + vpxor %ymm0, %ymm0, %ymm0 + vmovdqa %ymm0, (%rsp) + vmovdqa %ymm0, 32(%rsp) + movl $64, %edx + movq %rsp, %rsi + movq %rbx, %rdi + call .Lpoly1305_blocks_avx2_local +.Lpoly1305_finish_ext_avx2_38: + movq 8(%rbx), %rax + movq %rax, %rdx + salq $44, %rdx + orq (%rbx), %rdx + shrq $20, %rax + movl $24, %edi + shlx %rdi, 16(%rbx), %rcx + orq %rcx, %rax + movl 292(%rbx), %ecx + salq $32, %rcx + movl 284(%rbx), %esi + orq %rsi, %rcx + movl 308(%rbx), %esi + salq $32, %rsi + movl 300(%rbx), %edi + orq %rdi, %rsi + addq %rcx, %rdx + adcq %rsi, %rax + movq %rdx, (%r12) + movq %rax, 8(%r12) + vpxor %xmm0, %xmm0, %xmm0 + vmovdqu %ymm0, (%rbx) + vmovdqu %ymm0, 32(%rbx) + vmovdqu %ymm0, 64(%rbx) + vmovdqu %ymm0, 96(%rbx) + vmovdqu %ymm0, 128(%rbx) + vmovdqu %ymm0, 160(%rbx) + vmovdqu %ymm0, 192(%rbx) + vmovdqu %ymm0, 224(%rbx) + jmp .Lpoly1305_finish_ext_avx2_49 +.Lpoly1305_finish_ext_avx2_46: + movl $3, %r9d + movl $1, %edi + movl $10, %eax + jmp .Lpoly1305_finish_ext_avx2_39 +.Lpoly1305_finish_ext_avx2_47: + movl $3, %r9d + movl $0, %edi + movl $10, %eax +.Lpoly1305_finish_ext_avx2_39: + leaq 164(%rbx,%rax,8), %rdx + leaq 160(%rbx,%rdi,8), %rax + movq %rdi, %rcx + jmp .Lpoly1305_finish_ext_avx2_41 +.Lpoly1305_finish_ext_avx2_49: + movq %rbp, %rax + subq %rsp, %rax + leaq -24(%rbp), %rsp + vzeroall + popq %rbx + popq %r12 + popq %r13 + popq %rbp + addq $(8*5), %rax +ret +.size _gcry_poly1305_amd64_avx2_finish_ext,.-_gcry_poly1305_amd64_avx2_finish_ext; + +#endif diff --git a/cipher/poly1305-internal.h b/cipher/poly1305-internal.h index fa3fe75..0299c43 100644 --- a/cipher/poly1305-internal.h +++ b/cipher/poly1305-internal.h @@ -54,23 +54,40 @@ #endif +/* POLY1305_USE_AVX2 indicates whether to compile with AMD64 AVX2 code. */ +#undef POLY1305_USE_AVX2 +#if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) && \ + defined(ENABLE_AVX2_SUPPORT) +# define POLY1305_USE_AVX2 1 +# define POLY1305_AVX2_BLOCKSIZE 64 +# define POLY1305_AVX2_STATESIZE 328 +# define POLY1305_AVX2_ALIGNMENT 32 +#endif + + /* Largest block-size used in any implementation (optimized implementations * might use block-size multiple of 16). */ -#ifdef POLY1305_USE_SSE2 +#ifdef POLY1305_USE_AVX2 +# define POLY1305_LARGEST_BLOCKSIZE POLY1305_AVX2_BLOCKSIZE +#elif defined(POLY1305_USE_SSE2) # define POLY1305_LARGEST_BLOCKSIZE POLY1305_SSE2_BLOCKSIZE #else # define POLY1305_LARGEST_BLOCKSIZE POLY1305_REF_BLOCKSIZE #endif /* Largest state-size used in any implementation. */ -#ifdef POLY1305_USE_SSE2 +#ifdef POLY1305_USE_AVX2 +# define POLY1305_LARGEST_STATESIZE POLY1305_AVX2_STATESIZE +#elif defined(POLY1305_USE_SSE2) # define POLY1305_LARGEST_STATESIZE POLY1305_SSE2_STATESIZE #else # define POLY1305_LARGEST_STATESIZE POLY1305_REF_STATESIZE #endif /* Minimum alignment for state pointer passed to implementations. */ -#ifdef POLY1305_USE_SSE2 +#ifdef POLY1305_USE_AVX2 +# define POLY1305_STATE_ALIGNMENT POLY1305_AVX2_ALIGNMENT +#elif defined(POLY1305_USE_SSE2) # define POLY1305_STATE_ALIGNMENT POLY1305_SSE2_ALIGNMENT #else # define POLY1305_STATE_ALIGNMENT POLY1305_REF_ALIGNMENT diff --git a/cipher/poly1305.c b/cipher/poly1305.c index cd1902a..fe241c1 100644 --- a/cipher/poly1305.c +++ b/cipher/poly1305.c @@ -57,6 +57,25 @@ static const poly1305_ops_t poly1305_amd64_sse2_ops = { #endif +#ifdef POLY1305_USE_AVX2 + +void _gcry_poly1305_amd64_avx2_init_ext(void *state, const poly1305_key_t *key); +unsigned int _gcry_poly1305_amd64_avx2_finish_ext(void *state, const byte *m, + size_t remaining, + byte mac[16]); +unsigned int _gcry_poly1305_amd64_avx2_blocks(void *ctx, const byte *m, + size_t bytes); + +static const poly1305_ops_t poly1305_amd64_avx2_ops = { + POLY1305_AVX2_BLOCKSIZE, + _gcry_poly1305_amd64_avx2_init_ext, + _gcry_poly1305_amd64_avx2_blocks, + _gcry_poly1305_amd64_avx2_finish_ext +}; + +#endif + + #ifdef HAVE_U64_TYPEDEF /* Reference unoptimized poly1305 implementation using 32 bit * 32 bit = 64 bit @@ -616,6 +635,7 @@ _gcry_poly1305_init (poly1305_context_t * ctx, const byte * key, static int initialized; static const char *selftest_failed; poly1305_key_t keytmp; + unsigned int features = _gcry_get_hw_features (); if (!initialized) { @@ -637,6 +657,12 @@ _gcry_poly1305_init (poly1305_context_t * ctx, const byte * key, ctx->ops = &poly1305_default_ops; #endif +#ifdef POLY1305_USE_AVX2 + if (features & HWF_INTEL_AVX2) + ctx->ops = &poly1305_amd64_avx2_ops; +#endif + (void)features; + buf_cpy (keytmp.b, key, POLY1305_KEYLEN); poly1305_init (ctx, &keytmp); diff --git a/configure.ac b/configure.ac index 4dc36d5..47a322b 100644 --- a/configure.ac +++ b/configure.ac @@ -1825,6 +1825,7 @@ case "${host}" in x86_64-*-*) # Build with the assembly implementation GCRYPT_CIPHERS="$GCRYPT_CIPHERS poly1305-sse2-amd64.lo" + GCRYPT_CIPHERS="$GCRYPT_CIPHERS poly1305-avx2-amd64.lo" ;; esac commit 297532602ed2d881d8fdc393d1961068a143a891 Author: Jussi Kivilinna Date: Sun May 11 20:18:49 2014 +0300 poly1305: add AMD64/SSE2 optimized implementation * cipher/Makefile.am: Add 'poly1305-sse2-amd64.S'. * cipher/poly1305-internal.h (POLY1305_USE_SSE2) (POLY1305_SSE2_BLOCKSIZE, POLY1305_SSE2_STATESIZE) (POLY1305_SSE2_ALIGNMENT): New. (POLY1305_LARGEST_BLOCKSIZE, POLY1305_LARGEST_STATESIZE) (POLY1305_STATE_ALIGNMENT): Use SSE2 versions when needed. * cipher/poly1305-sse2-amd64.S: New. * cipher/poly1305.c [POLY1305_USE_SSE2] (_gcry_poly1305_amd64_sse2_init_ext) (_gcry_poly1305_amd64_sse2_finish_ext) (_gcry_poly1305_amd64_sse2_blocks, poly1305_amd64_sse2_ops): New. (_gcry_polu1305_init) [POLY1305_USE_SSE2]: Use SSE2 version. * configure.ac [host=x86_64]: Add 'poly1305-sse2-amd64.lo'. -- Add Andrew Moon's public domain SSE2 implementation of Poly1305. Original source is available at: https://github.com/floodyberry/poly1305-opt Benchmarks on Intel i5-4570 (haswell): Old: | nanosecs/byte mebibytes/sec cycles/byte POLY1305 | 0.844 ns/B 1130.2 MiB/s 2.70 c/B New: | nanosecs/byte mebibytes/sec cycles/byte POLY1305 | 0.448 ns/B 2129.5 MiB/s 1.43 c/B Benchmarks on Intel i5-2450M (sandy-bridge): Old: | nanosecs/byte mebibytes/sec cycles/byte POLY1305 | 1.25 ns/B 763.0 MiB/s 3.12 c/B New: | nanosecs/byte mebibytes/sec cycles/byte POLY1305 | 0.605 ns/B 1575.9 MiB/s 1.51 c/B Signed-off-by: Jussi Kivilinna diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 4468647..a32ae89 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -72,6 +72,7 @@ gost28147.c gost.h \ gostr3411-94.c \ md4.c \ md5.c \ +poly1305-sse2-amd64.S \ rijndael.c rijndael-tables.h rijndael-amd64.S rijndael-arm.S \ rmd160.c \ rsa.c \ diff --git a/cipher/poly1305-internal.h b/cipher/poly1305-internal.h index d2c6b5c..fa3fe75 100644 --- a/cipher/poly1305-internal.h +++ b/cipher/poly1305-internal.h @@ -44,15 +44,37 @@ #define POLY1305_REF_ALIGNMENT sizeof(void *) +/* POLY1305_USE_SSE2 indicates whether to compile with AMD64 SSE2 code. */ +#undef POLY1305_USE_SSE2 +#if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) +# define POLY1305_USE_SSE2 1 +# define POLY1305_SSE2_BLOCKSIZE 32 +# define POLY1305_SSE2_STATESIZE 248 +# define POLY1305_SSE2_ALIGNMENT 16 +#endif + + /* Largest block-size used in any implementation (optimized implementations * might use block-size multiple of 16). */ -#define POLY1305_LARGEST_BLOCKSIZE POLY1305_REF_BLOCKSIZE +#ifdef POLY1305_USE_SSE2 +# define POLY1305_LARGEST_BLOCKSIZE POLY1305_SSE2_BLOCKSIZE +#else +# define POLY1305_LARGEST_BLOCKSIZE POLY1305_REF_BLOCKSIZE +#endif /* Largest state-size used in any implementation. */ -#define POLY1305_LARGEST_STATESIZE POLY1305_REF_STATESIZE +#ifdef POLY1305_USE_SSE2 +# define POLY1305_LARGEST_STATESIZE POLY1305_SSE2_STATESIZE +#else +# define POLY1305_LARGEST_STATESIZE POLY1305_REF_STATESIZE +#endif /* Minimum alignment for state pointer passed to implementations. */ -#define POLY1305_STATE_ALIGNMENT POLY1305_REF_ALIGNMENT +#ifdef POLY1305_USE_SSE2 +# define POLY1305_STATE_ALIGNMENT POLY1305_SSE2_ALIGNMENT +#else +# define POLY1305_STATE_ALIGNMENT POLY1305_REF_ALIGNMENT +#endif typedef struct poly1305_key_s diff --git a/cipher/poly1305-sse2-amd64.S b/cipher/poly1305-sse2-amd64.S new file mode 100644 index 0000000..106b119 --- /dev/null +++ b/cipher/poly1305-sse2-amd64.S @@ -0,0 +1,1035 @@ +/* poly1305-sse2-amd64.S - AMD64/SSE2 implementation of Poly1305 + * + * Copyright (C) 2014 Jussi Kivilinna + * + * 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, see . + */ + +/* + * Based on public domain implementation by Andrew Moon at + * https://github.com/floodyberry/poly1305-opt + */ + +#include + +#if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) + +.text + + +.align 8 +.globl _gcry_poly1305_amd64_sse2_init_ext +.type _gcry_poly1305_amd64_sse2_init_ext, at function; +_gcry_poly1305_amd64_sse2_init_ext: +.Lpoly1305_init_ext_x86_local: + xor %edx, %edx + pushq %r12 + pushq %r13 + pushq %r14 + movq %rdx, %r10 + movq $-1, %rcx + testq %r10, %r10 + pxor %xmm0, %xmm0 + movq $0xfffffc0ffff, %r9 + movdqa %xmm0, (%rdi) + cmove %rcx, %r10 + movdqa %xmm0, 16(%rdi) + movq $0xffc0fffffff, %rcx + movdqa %xmm0, 32(%rdi) + movdqa %xmm0, 48(%rdi) + movdqa %xmm0, 64(%rdi) + movq 8(%rsi), %r11 + movq %r11, %r8 + movq (%rsi), %r12 + andq %r12, %rcx + shrq $44, %r12 + shlq $20, %r8 + shrq $24, %r11 + orq %r8, %r12 + movq $0xffffffc0f, %r8 + andq %r9, %r12 + andq %r8, %r11 + movl %ecx, %r8d + andl $67108863, %r8d + movq %rcx, %r9 + movl %r8d, 84(%rdi) + movq %r12, %r8 + shrq $26, %r9 + shlq $18, %r8 + orq %r8, %r9 + movq %r12, %r8 + shrq $8, %r8 + andl $67108863, %r9d + andl $67108863, %r8d + movl %r9d, 92(%rdi) + movq %r12, %r9 + movl %r8d, 100(%rdi) + movq %r11, %r8 + shrq $34, %r9 + shlq $10, %r8 + orq %r8, %r9 + movq %r11, %r8 + shrq $16, %r8 + andl $67108863, %r9d + movl %r9d, 108(%rdi) + cmpq $16, %r10 + movl %r8d, 116(%rdi) + movl 16(%rsi), %r8d + movl %r8d, 124(%rdi) + movl 20(%rsi), %r8d + movl %r8d, 132(%rdi) + movl 24(%rsi), %r8d + movl %r8d, 140(%rdi) + movl 28(%rsi), %esi + movl %esi, 148(%rdi) + jbe .Lpoly1305_init_ext_sse2_done + lea (%r11,%r11,4), %r14 + shlq $2, %r14 + lea (%r12,%r12), %rax + mulq %r14 + movq %rax, %r13 + movq %rcx, %rax + movq %rdx, %r8 + mulq %rcx + addq %rax, %r13 + lea (%rcx,%rcx), %rax + movq %r13, %r9 + adcq %rdx, %r8 + mulq %r12 + shlq $20, %r8 + movq %rax, %rsi + shrq $44, %r9 + movq %r11, %rax + orq %r9, %r8 + movq %rdx, %r9 + mulq %r14 + addq %rax, %rsi + movq %rcx, %rax + adcq %rdx, %r9 + addq %r11, %r11 + mulq %r11 + addq %rsi, %r8 + movq %rax, %r11 + movq %r12, %rax + movq %rdx, %rcx + adcq $0, %r9 + mulq %r12 + addq %rax, %r11 + movq %r8, %rsi + adcq %rdx, %rcx + shlq $20, %r9 + shrq $44, %rsi + orq %rsi, %r9 + movq $0xfffffffffff, %rsi + addq %r11, %r9 + movq %r9, %r12 + adcq $0, %rcx + andq %rsi, %r13 + shlq $22, %rcx + andq %rsi, %r8 + shrq $42, %r12 + orq %r12, %rcx + movq %rsi, %r12 + lea (%rcx,%rcx,4), %rcx + addq %rcx, %r13 + movq %rsi, %rcx + andq %r13, %rcx + shrq $44, %r13 + movq %rcx, %r14 + addq %r13, %r8 + movq $0x3ffffffffff, %r13 + andq %r8, %r12 + andq %r13, %r9 + shrq $44, %r8 + movq %r12, %r11 + addq %r8, %r9 + movq %r12, %rax + movq %r9, %r13 + movl %ecx, %r8d + shrq $26, %r14 + andl $67108863, %r8d + shlq $18, %r11 + shrq $34, %rax + orq %r11, %r14 + shlq $10, %r13 + movq %r12, %r11 + orq %r13, %rax + movq %r9, %r13 + shrq $8, %r11 + shrq $16, %r13 + andl $67108863, %r14d + andl $67108863, %r11d + andl $67108863, %eax + movl %r8d, 88(%rdi) + cmpq $64, %r10 + movl %r8d, 80(%rdi) + movl %r14d, 104(%rdi) + movl %r14d, 96(%rdi) + movl %r11d, 120(%rdi) + movl %r11d, 112(%rdi) + movl %eax, 136(%rdi) + movl %eax, 128(%rdi) + movl %r13d, 152(%rdi) + movl %r13d, 144(%rdi) + jbe .Lpoly1305_init_ext_sse2_done + lea (%r9,%r9,4), %r14 + shlq $2, %r14 + lea (%r12,%r12), %rax + mulq %r14 + movq %rax, %r8 + movq %rcx, %rax + movq %rdx, %r10 + mulq %rcx + addq %rax, %r8 + lea (%rcx,%rcx), %rax + movq %r8, %r11 + adcq %rdx, %r10 + andq %rsi, %r8 + mulq %r12 + shlq $20, %r10 + movq %rax, %r13 + shrq $44, %r11 + movq %r9, %rax + orq %r11, %r10 + movq %rdx, %r11 + mulq %r14 + addq %rax, %r13 + movq %rcx, %rax + adcq %rdx, %r11 + addq %r9, %r9 + mulq %r9 + addq %r13, %r10 + movq %rax, %r9 + movq %r12, %rax + movq %rdx, %rcx + adcq $0, %r11 + mulq %r12 + addq %rax, %r9 + movq %r10, %r13 + adcq %rdx, %rcx + andq %rsi, %r10 + shlq $20, %r11 + shrq $44, %r13 + orq %r13, %r11 + addq %r9, %r11 + movq %rsi, %r9 + movq %r11, %r12 + adcq $0, %rcx + shlq $22, %rcx + shrq $42, %r12 + orq %r12, %rcx + lea (%rcx,%rcx,4), %rcx + addq %rcx, %r8 + andq %r8, %r9 + shrq $44, %r8 + movl %r9d, %eax + addq %r8, %r10 + movq $0x3ffffffffff, %r8 + andq %r10, %rsi + andq %r8, %r11 + shrq $44, %r10 + movq %rsi, %r8 + addq %r10, %r11 + andl $67108863, %eax + shrq $26, %r9 + movq %r11, %r10 + shlq $18, %r8 + shlq $10, %r10 + orq %r8, %r9 + movq %rsi, %r8 + shrq $34, %rsi + andl $67108863, %r9d + shrq $8, %r8 + orq %r10, %rsi + shrq $16, %r11 + andl $67108863, %r8d + andl $67108863, %esi + movl %eax, 168(%rdi) + movl %eax, 160(%rdi) + movl %r9d, 184(%rdi) + movl %r9d, 176(%rdi) + movl %r8d, 200(%rdi) + movl %r8d, 192(%rdi) + movl %esi, 216(%rdi) + movl %esi, 208(%rdi) + movl %r11d, 232(%rdi) + movl %r11d, 224(%rdi) +.Lpoly1305_init_ext_sse2_done: + movq $0, 240(%rdi) + popq %r14 + popq %r13 + popq %r12 + ret +.size _gcry_poly1305_amd64_sse2_init_ext,.-_gcry_poly1305_amd64_sse2_init_ext; + + +.align 8 +.globl _gcry_poly1305_amd64_sse2_finish_ext +.type _gcry_poly1305_amd64_sse2_finish_ext, at function; +_gcry_poly1305_amd64_sse2_finish_ext: +.Lpoly1305_finish_ext_x86_local: + pushq %rbp + movq %rsp, %rbp + subq $64, %rsp + andq $~63, %rsp + movq %rdx, 32(%rsp) + movq %rcx, 40(%rsp) + andq %rdx, %rdx + jz .Lpoly1305_finish_x86_no_leftover + pxor %xmm0, %xmm0 + movdqa %xmm0, 0+0(%rsp) + movdqa %xmm0, 16+0(%rsp) + leaq 0(%rsp), %r8 + testq $16, %rdx + jz .Lpoly1305_finish_x86_skip16 + movdqu 0(%rsi), %xmm0 + movdqa %xmm0, 0(%r8) + addq $16, %rsi + addq $16, %r8 +.Lpoly1305_finish_x86_skip16: + testq $8, %rdx + jz .Lpoly1305_finish_x86_skip8 + movq 0(%rsi), %rax + movq %rax, 0(%r8) + addq $8, %rsi + addq $8, %r8 +.Lpoly1305_finish_x86_skip8: + testq $4, %rdx + jz .Lpoly1305_finish_x86_skip4 + movl 0(%rsi), %eax + movl %eax, 0(%r8) + addq $4, %rsi + addq $4, %r8 +.Lpoly1305_finish_x86_skip4: + testq $2, %rdx + jz .Lpoly1305_finish_x86_skip2 + movw 0(%rsi), %ax + movw %ax, 0(%r8) + addq $2, %rsi + addq $2, %r8 +.Lpoly1305_finish_x86_skip2: + testq $1, %rdx + jz .Lpoly1305_finish_x86_skip1 + movb 0(%rsi), %al + movb %al, 0(%r8) + addq $1, %r8 +.Lpoly1305_finish_x86_skip1: + cmpq $16, %rdx + je .Lpoly1305_finish_x86_is16 + movb $1, 0(%r8) +.Lpoly1305_finish_x86_is16: + movq $4, %rax + jae .Lpoly1305_finish_x86_16andover + movq $8, %rax +.Lpoly1305_finish_x86_16andover: + orq %rax, 240(%rdi) + leaq 0(%rsp), %rsi + movq $32, %rdx + callq .Lpoly1305_blocks_x86_local +.Lpoly1305_finish_x86_no_leftover: + testq $1, 240(%rdi) + jz .Lpoly1305_finish_x86_not_started + movq 32(%rsp), %rdx + andq %rdx, %rdx + jz .Lpoly1305_finish_x86_r2r + cmpq $16, %rdx + jg .Lpoly1305_finish_x86_r2r + xorl %r10d, %r10d + movl 84(%rdi), %eax + movl 92(%rdi), %ecx + movl 100(%rdi), %edx + movl 108(%rdi), %r8d + movl 116(%rdi), %r9d + movl %eax, 80(%rdi) + movl $1, 8+80(%rdi) + movl %ecx, 96(%rdi) + movl %r10d, 8+96(%rdi) + movl %edx, 112(%rdi) + movl %r10d, 8+112(%rdi) + movl %r8d, 128(%rdi) + movl %r10d, 8+128(%rdi) + movl %r9d, 144(%rdi) + movl %r10d, 8+144(%rdi) + jmp .Lpoly1305_finish_x86_combine +.Lpoly1305_finish_x86_r2r: + movl 84(%rdi), %eax + movl 92(%rdi), %ecx + movl 100(%rdi), %edx + movl 108(%rdi), %r8d + movl 116(%rdi), %r9d + movl %eax, 8+80(%rdi) + movl %ecx, 8+96(%rdi) + movl %edx, 8+112(%rdi) + movl %r8d, 8+128(%rdi) + movl %r9d, 8+144(%rdi) +.Lpoly1305_finish_x86_combine: + xorq %rsi, %rsi + movq $32, %rdx + callq .Lpoly1305_blocks_x86_local +.Lpoly1305_finish_x86_not_started: + movq 0(%rdi), %r8 + movq 8(%rdi), %r9 + movq %r9, %r10 + movq 16(%rdi), %r11 + shlq $44, %r9 + shrq $20, %r10 + shlq $24, %r11 + orq %r9, %r8 + orq %r11, %r10 + pxor %xmm0, %xmm0 + movl 124(%rdi), %eax + movl 132(%rdi), %ecx + movl 140(%rdi), %edx + movl 148(%rdi), %esi + movq 40(%rsp), %r11 + shlq $32, %rcx + shlq $32, %rsi + orq %rcx, %rax + orq %rsi, %rdx + addq %r8, %rax + adcq %r10, %rdx + movq %rax, 0(%r11) + movq %rdx, 8(%r11) + movq %rbp, %rax + subq %rsp, %rax + movq %rbp, %rsp + movdqa %xmm0, 0(%rdi) + movdqa %xmm0, 16(%rdi) + movdqa %xmm0, 32(%rdi) + movdqa %xmm0, 48(%rdi) + movdqa %xmm0, 64(%rdi) + movdqa %xmm0, 80(%rdi) + movdqa %xmm0, 96(%rdi) + movdqa %xmm0, 112(%rdi) + movdqa %xmm0, 128(%rdi) + movdqa %xmm0, 144(%rdi) + movdqa %xmm0, 160(%rdi) + movdqa %xmm0, 176(%rdi) + movdqa %xmm0, 192(%rdi) + movdqa %xmm0, 208(%rdi) + movdqa %xmm0, 224(%rdi) + popq %rbp + addq $8, %rax + ret +.size _gcry_poly1305_amd64_sse2_finish_ext,.-_gcry_poly1305_amd64_sse2_finish_ext; + + +.align 8 +.globl _gcry_poly1305_amd64_sse2_blocks +.type _gcry_poly1305_amd64_sse2_blocks, at function; +_gcry_poly1305_amd64_sse2_blocks: +.Lpoly1305_blocks_x86_local: + pushq %rbp + movq %rsp, %rbp + pushq %rbx + andq $-64, %rsp + subq $328, %rsp + movq 240(%rdi), %rax + movl $(1<<24), %r8d + movl $((1<<26)-1), %r9d + movd %r8, %xmm0 + movd %r9, %xmm5 + pshufd $0x44, %xmm0, %xmm0 + pshufd $0x44, %xmm5, %xmm5 + testb $4, %al + je .Lpoly1305_blocks_x86_3 + psrldq $8, %xmm0 +.Lpoly1305_blocks_x86_3: + testb $8, %al + je .Lpoly1305_blocks_x86_4 + pxor %xmm0, %xmm0 +.Lpoly1305_blocks_x86_4: + movdqa %xmm0, 168(%rsp) + testb $1, %al + jne .Lpoly1305_blocks_x86_5 + movq 16(%rsi), %xmm0 + movdqa %xmm5, %xmm7 + movdqa %xmm5, %xmm10 + movq (%rsi), %xmm6 + orq $1, %rax + subq $32, %rdx + movq 8(%rsi), %xmm1 + punpcklqdq %xmm0, %xmm6 + movq 24(%rsi), %xmm0 + pand %xmm6, %xmm7 + movdqa %xmm6, %xmm9 + psrlq $52, %xmm6 + addq $32, %rsi + punpcklqdq %xmm0, %xmm1 + movdqa %xmm1, %xmm0 + psrlq $26, %xmm9 + psllq $12, %xmm0 + movq %rax, 240(%rdi) + pand %xmm5, %xmm9 + por %xmm0, %xmm6 + psrlq $40, %xmm1 + pand %xmm6, %xmm10 + por 168(%rsp), %xmm1 + psrlq $26, %xmm6 + pand %xmm5, %xmm6 +.Lpoly1305_blocks_x86_6: + movdqa 80(%rdi), %xmm13 + cmpq $63, %rdx + movl $(5), %r8d + movd %r8, %xmm14 + pshufd $0x44, %xmm14, %xmm14 + movdqa 96(%rdi), %xmm15 + movdqa %xmm13, -8(%rsp) + movdqa 112(%rdi), %xmm0 + movdqa %xmm14, 136(%rsp) + movdqa 128(%rdi), %xmm3 + movdqa %xmm15, 312(%rsp) + pmuludq %xmm14, %xmm15 + movdqa 144(%rdi), %xmm13 + movdqa %xmm0, 232(%rsp) + pmuludq %xmm14, %xmm0 + movdqa %xmm3, 152(%rsp) + pmuludq %xmm14, %xmm3 + movdqa %xmm13, 56(%rsp) + pmuludq %xmm14, %xmm13 + movdqa %xmm15, 40(%rsp) + movdqa %xmm0, -24(%rsp) + movdqa %xmm3, -40(%rsp) + movdqa %xmm13, -56(%rsp) + jbe .Lpoly1305_blocks_x86_7 + movdqa 192(%rdi), %xmm15 + leaq 32(%rsi), %rax + movq %rdx, %rcx + movdqa 176(%rdi), %xmm14 + movdqa %xmm15, %xmm2 + movdqa 208(%rdi), %xmm0 + movdqa %xmm15, 216(%rsp) + movdqa %xmm14, 296(%rsp) + movdqa 224(%rdi), %xmm3 + pmuludq 136(%rsp), %xmm14 + movdqa -24(%rsp), %xmm13 + movdqa %xmm14, 8(%rsp) + pmuludq 136(%rsp), %xmm2 + movdqa -40(%rsp), %xmm14 + movdqa %xmm0, 120(%rsp) + pmuludq 136(%rsp), %xmm0 + movdqa %xmm3, 24(%rsp) + movdqa 160(%rdi), %xmm12 + movdqa %xmm0, %xmm8 + movdqa -56(%rsp), %xmm15 + movdqa %xmm13, 88(%rsp) + pmuludq 136(%rsp), %xmm3 + movdqa %xmm2, 104(%rsp) + movdqa %xmm0, %xmm13 + movdqa -8(%rsp), %xmm11 + movdqa %xmm3, 280(%rsp) + movdqa %xmm2, %xmm3 + movdqa %xmm0, 200(%rsp) + movdqa %xmm14, 184(%rsp) + movdqa %xmm15, 264(%rsp) + jmp .Lpoly1305_blocks_x86_8 +.p2align 6,,63 +.Lpoly1305_blocks_x86_13: + movdqa 200(%rsp), %xmm13 + movdqa %xmm3, %xmm6 + movdqa 200(%rsp), %xmm8 + movdqa 104(%rsp), %xmm3 +.Lpoly1305_blocks_x86_8: + movdqa 8(%rsp), %xmm4 + pmuludq %xmm6, %xmm3 + subq $64, %rcx + pmuludq %xmm10, %xmm8 + movdqa 104(%rsp), %xmm2 + movdqa 200(%rsp), %xmm0 + pmuludq %xmm1, %xmm4 + movdqa 280(%rsp), %xmm15 + pmuludq %xmm6, %xmm13 + movdqa 280(%rsp), %xmm14 + pmuludq %xmm1, %xmm0 + paddq %xmm3, %xmm4 + pmuludq %xmm1, %xmm2 + movdqa 280(%rsp), %xmm3 + paddq %xmm8, %xmm4 + pmuludq %xmm9, %xmm15 + movdqa 280(%rsp), %xmm8 + pmuludq %xmm10, %xmm14 + pmuludq %xmm6, %xmm8 + paddq %xmm13, %xmm2 + movdqa %xmm6, %xmm13 + pmuludq %xmm1, %xmm3 + paddq %xmm15, %xmm4 + movdqa 296(%rsp), %xmm15 + pmuludq %xmm12, %xmm13 + paddq %xmm14, %xmm2 + movdqa %xmm7, %xmm14 + paddq %xmm8, %xmm0 + pmuludq %xmm12, %xmm14 + movdqa %xmm9, %xmm8 + pmuludq 296(%rsp), %xmm6 + pmuludq %xmm12, %xmm8 + movdqa %xmm6, 248(%rsp) + pmuludq %xmm10, %xmm15 + movq -16(%rax), %xmm6 + paddq %xmm13, %xmm3 + movdqa %xmm10, %xmm13 + paddq %xmm14, %xmm4 + movq -8(%rax), %xmm14 + paddq %xmm8, %xmm2 + movq -32(%rax), %xmm8 + pmuludq %xmm12, %xmm13 + paddq %xmm15, %xmm3 + pmuludq %xmm12, %xmm1 + movdqa 216(%rsp), %xmm15 + pmuludq 216(%rsp), %xmm10 + punpcklqdq %xmm6, %xmm8 + movq -24(%rax), %xmm6 + pmuludq %xmm9, %xmm15 + paddq %xmm13, %xmm0 + movdqa 296(%rsp), %xmm13 + paddq 248(%rsp), %xmm1 + punpcklqdq %xmm14, %xmm6 + movdqa 296(%rsp), %xmm14 + pmuludq %xmm9, %xmm13 + pmuludq 120(%rsp), %xmm9 + movdqa %xmm15, 72(%rsp) + paddq %xmm10, %xmm1 + movdqa 216(%rsp), %xmm15 + pmuludq %xmm7, %xmm14 + movdqa %xmm6, %xmm10 + paddq %xmm9, %xmm1 + pmuludq %xmm7, %xmm15 + paddq %xmm13, %xmm0 + paddq 72(%rsp), %xmm3 + movdqa 120(%rsp), %xmm13 + psllq $12, %xmm10 + paddq %xmm14, %xmm2 + movdqa %xmm5, %xmm14 + pand %xmm8, %xmm14 + pmuludq %xmm7, %xmm13 + paddq %xmm15, %xmm0 + movdqa %xmm14, 248(%rsp) + movdqa %xmm8, %xmm14 + psrlq $52, %xmm8 + movdqu (%rax), %xmm9 + por %xmm10, %xmm8 + pmuludq 24(%rsp), %xmm7 + movdqu 16(%rax), %xmm10 + paddq %xmm13, %xmm3 + pxor %xmm13, %xmm13 + movdqa %xmm9, %xmm15 + paddq %xmm7, %xmm1 + movdqa %xmm6, %xmm7 + movdqa %xmm10, -72(%rsp) + punpckldq %xmm10, %xmm15 + movdqa %xmm15, %xmm10 + punpckldq %xmm13, %xmm10 + punpckhdq -72(%rsp), %xmm9 + psrlq $40, %xmm6 + movdqa %xmm10, 72(%rsp) + movdqa %xmm9, %xmm10 + punpckhdq %xmm13, %xmm9 + psllq $18, %xmm9 + paddq 72(%rsp), %xmm4 + addq $64, %rax + paddq %xmm9, %xmm3 + movdqa 40(%rsp), %xmm9 + cmpq $63, %rcx + punpckhdq %xmm13, %xmm15 + psllq $6, %xmm15 + punpckldq %xmm13, %xmm10 + paddq %xmm15, %xmm2 + psllq $12, %xmm10 + por 168(%rsp), %xmm6 + pmuludq %xmm6, %xmm9 + movdqa 88(%rsp), %xmm15 + paddq %xmm10, %xmm0 + movdqa 88(%rsp), %xmm13 + psrlq $14, %xmm7 + pand %xmm5, %xmm8 + movdqa 184(%rsp), %xmm10 + pand %xmm5, %xmm7 + pmuludq %xmm7, %xmm15 + paddq %xmm9, %xmm4 + pmuludq %xmm6, %xmm13 + movdqa 184(%rsp), %xmm9 + paddq 168(%rsp), %xmm1 + pmuludq %xmm7, %xmm10 + pmuludq %xmm6, %xmm9 + paddq %xmm15, %xmm4 + movdqa 184(%rsp), %xmm15 + paddq %xmm13, %xmm2 + psrlq $26, %xmm14 + movdqa 264(%rsp), %xmm13 + paddq %xmm10, %xmm2 + pmuludq %xmm8, %xmm15 + pand %xmm5, %xmm14 + paddq %xmm9, %xmm0 + pmuludq %xmm6, %xmm13 + movdqa 264(%rsp), %xmm9 + movdqa 264(%rsp), %xmm10 + pmuludq %xmm11, %xmm6 + pmuludq %xmm8, %xmm9 + paddq %xmm15, %xmm4 + movdqa 264(%rsp), %xmm15 + pmuludq %xmm14, %xmm10 + paddq %xmm13, %xmm3 + movdqa %xmm7, %xmm13 + pmuludq %xmm7, %xmm15 + paddq %xmm6, %xmm1 + movdqa 312(%rsp), %xmm6 + paddq %xmm9, %xmm2 + pmuludq %xmm11, %xmm13 + movdqa 248(%rsp), %xmm9 + paddq %xmm10, %xmm4 + pmuludq %xmm8, %xmm6 + pmuludq 312(%rsp), %xmm7 + paddq %xmm15, %xmm0 + movdqa %xmm9, %xmm10 + movdqa %xmm14, %xmm15 + pmuludq %xmm11, %xmm10 + paddq %xmm13, %xmm3 + movdqa %xmm8, %xmm13 + pmuludq %xmm11, %xmm13 + paddq %xmm6, %xmm3 + paddq %xmm7, %xmm1 + movdqa 232(%rsp), %xmm6 + pmuludq %xmm11, %xmm15 + pmuludq 232(%rsp), %xmm8 + paddq %xmm10, %xmm4 + paddq %xmm8, %xmm1 + movdqa 312(%rsp), %xmm10 + paddq %xmm13, %xmm0 + pmuludq %xmm14, %xmm6 + movdqa 312(%rsp), %xmm13 + pmuludq %xmm9, %xmm10 + paddq %xmm15, %xmm2 + movdqa 232(%rsp), %xmm7 + pmuludq %xmm14, %xmm13 + pmuludq 152(%rsp), %xmm14 + paddq %xmm14, %xmm1 + pmuludq %xmm9, %xmm7 + paddq %xmm6, %xmm3 + paddq %xmm10, %xmm2 + movdqa 152(%rsp), %xmm10 + paddq %xmm13, %xmm0 + pmuludq %xmm9, %xmm10 + paddq %xmm7, %xmm0 + movdqa %xmm4, %xmm7 + psrlq $26, %xmm7 + pmuludq 56(%rsp), %xmm9 + pand %xmm5, %xmm4 + paddq %xmm7, %xmm2 + paddq %xmm9, %xmm1 + paddq %xmm10, %xmm3 + movdqa %xmm2, %xmm7 + movdqa %xmm2, %xmm9 + movdqa %xmm3, %xmm6 + psrlq $26, %xmm7 + pand %xmm5, %xmm3 + psrlq $26, %xmm6 + paddq %xmm7, %xmm0 + pand %xmm5, %xmm9 + paddq %xmm6, %xmm1 + movdqa %xmm0, %xmm10 + movdqa %xmm1, %xmm6 + pand %xmm5, %xmm10 + pand %xmm5, %xmm1 + psrlq $26, %xmm6 + pmuludq 136(%rsp), %xmm6 + paddq %xmm6, %xmm4 + movdqa %xmm0, %xmm6 + psrlq $26, %xmm6 + movdqa %xmm4, %xmm2 + movdqa %xmm4, %xmm7 + paddq %xmm6, %xmm3 + psrlq $26, %xmm2 + pand %xmm5, %xmm7 + movdqa %xmm3, %xmm0 + paddq %xmm2, %xmm9 + pand %xmm5, %xmm3 + psrlq $26, %xmm0 + paddq %xmm0, %xmm1 + ja .Lpoly1305_blocks_x86_13 + leaq -64(%rdx), %rax + movdqa %xmm3, %xmm6 + andl $63, %edx + andq $-64, %rax + leaq 64(%rsi,%rax), %rsi +.Lpoly1305_blocks_x86_7: + cmpq $31, %rdx + jbe .Lpoly1305_blocks_x86_9 + movdqa -24(%rsp), %xmm13 + movdqa %xmm6, %xmm0 + movdqa %xmm6, %xmm3 + movdqa 40(%rsp), %xmm11 + movdqa %xmm1, %xmm12 + testq %rsi, %rsi + movdqa -40(%rsp), %xmm2 + pmuludq %xmm13, %xmm0 + movdqa %xmm1, %xmm8 + pmuludq %xmm1, %xmm11 + movdqa %xmm10, %xmm4 + movdqa %xmm1, %xmm14 + pmuludq %xmm2, %xmm3 + movdqa %xmm6, %xmm15 + pmuludq %xmm1, %xmm13 + movdqa %xmm7, %xmm1 + pmuludq %xmm2, %xmm12 + paddq %xmm0, %xmm11 + movdqa -56(%rsp), %xmm0 + pmuludq %xmm10, %xmm2 + paddq %xmm3, %xmm13 + pmuludq %xmm0, %xmm4 + movdqa %xmm9, %xmm3 + pmuludq %xmm0, %xmm3 + paddq %xmm2, %xmm11 + pmuludq %xmm0, %xmm8 + movdqa %xmm6, %xmm2 + pmuludq %xmm0, %xmm2 + movdqa -8(%rsp), %xmm0 + paddq %xmm4, %xmm13 + movdqa 312(%rsp), %xmm4 + paddq %xmm3, %xmm11 + pmuludq 312(%rsp), %xmm6 + movdqa 312(%rsp), %xmm3 + pmuludq %xmm0, %xmm1 + paddq %xmm2, %xmm12 + pmuludq %xmm0, %xmm15 + movdqa %xmm9, %xmm2 + pmuludq %xmm0, %xmm2 + pmuludq %xmm7, %xmm3 + paddq %xmm1, %xmm11 + movdqa 232(%rsp), %xmm1 + pmuludq %xmm0, %xmm14 + paddq %xmm15, %xmm8 + pmuludq %xmm10, %xmm0 + paddq %xmm2, %xmm13 + movdqa 312(%rsp), %xmm2 + pmuludq %xmm10, %xmm4 + paddq %xmm3, %xmm13 + movdqa 152(%rsp), %xmm3 + pmuludq %xmm9, %xmm2 + paddq %xmm6, %xmm14 + pmuludq 232(%rsp), %xmm10 + paddq %xmm0, %xmm12 + pmuludq %xmm9, %xmm1 + paddq %xmm10, %xmm14 + movdqa 232(%rsp), %xmm0 + pmuludq %xmm7, %xmm3 + paddq %xmm4, %xmm8 + pmuludq 152(%rsp), %xmm9 + paddq %xmm2, %xmm12 + paddq %xmm9, %xmm14 + pmuludq %xmm7, %xmm0 + paddq %xmm1, %xmm8 + pmuludq 56(%rsp), %xmm7 + paddq %xmm3, %xmm8 + paddq %xmm7, %xmm14 + paddq %xmm0, %xmm12 + je .Lpoly1305_blocks_x86_10 + movdqu (%rsi), %xmm1 + pxor %xmm0, %xmm0 + paddq 168(%rsp), %xmm14 + movdqu 16(%rsi), %xmm2 + movdqa %xmm1, %xmm3 + punpckldq %xmm2, %xmm3 + punpckhdq %xmm2, %xmm1 + movdqa %xmm3, %xmm4 + movdqa %xmm1, %xmm2 + punpckldq %xmm0, %xmm4 + punpckhdq %xmm0, %xmm3 + punpckhdq %xmm0, %xmm1 + punpckldq %xmm0, %xmm2 + movdqa %xmm2, %xmm0 + psllq $6, %xmm3 + paddq %xmm4, %xmm11 + psllq $12, %xmm0 + paddq %xmm3, %xmm13 + psllq $18, %xmm1 + paddq %xmm0, %xmm12 + paddq %xmm1, %xmm8 +.Lpoly1305_blocks_x86_10: + movdqa %xmm11, %xmm9 + movdqa %xmm8, %xmm1 + movdqa %xmm11, %xmm7 + psrlq $26, %xmm9 + movdqa %xmm8, %xmm6 + pand %xmm5, %xmm7 + paddq %xmm13, %xmm9 + psrlq $26, %xmm1 + pand %xmm5, %xmm6 + movdqa %xmm9, %xmm10 + paddq %xmm14, %xmm1 + pand %xmm5, %xmm9 + psrlq $26, %xmm10 + movdqa %xmm1, %xmm0 + pand %xmm5, %xmm1 + paddq %xmm12, %xmm10 + psrlq $26, %xmm0 + pmuludq 136(%rsp), %xmm0 + movdqa %xmm10, %xmm2 + paddq %xmm0, %xmm7 + psrlq $26, %xmm2 + movdqa %xmm7, %xmm0 + pand %xmm5, %xmm10 + paddq %xmm2, %xmm6 + psrlq $26, %xmm0 + pand %xmm5, %xmm7 + movdqa %xmm6, %xmm2 + paddq %xmm0, %xmm9 + pand %xmm5, %xmm6 + psrlq $26, %xmm2 + paddq %xmm2, %xmm1 +.Lpoly1305_blocks_x86_9: + testq %rsi, %rsi + je .Lpoly1305_blocks_x86_11 + movdqa %xmm7, 0(%rdi) + movdqa %xmm9, 16(%rdi) + movdqa %xmm10, 32(%rdi) + movdqa %xmm6, 48(%rdi) + movdqa %xmm1, 64(%rdi) + movq -8(%rbp), %rbx + leave + ret +.Lpoly1305_blocks_x86_5: + movdqa 0(%rdi), %xmm7 + movdqa 16(%rdi), %xmm9 + movdqa 32(%rdi), %xmm10 + movdqa 48(%rdi), %xmm6 + movdqa 64(%rdi), %xmm1 + jmp .Lpoly1305_blocks_x86_6 +.Lpoly1305_blocks_x86_11: + movdqa %xmm7, %xmm0 + movdqa %xmm9, %xmm2 + movdqa %xmm6, %xmm3 + psrldq $8, %xmm0 + movabsq $4398046511103, %rbx + paddq %xmm0, %xmm7 + psrldq $8, %xmm2 + movdqa %xmm10, %xmm0 + movd %xmm7, %edx + paddq %xmm2, %xmm9 + psrldq $8, %xmm0 + movl %edx, %ecx + movd %xmm9, %eax + paddq %xmm0, %xmm10 + shrl $26, %ecx + psrldq $8, %xmm3 + movdqa %xmm1, %xmm0 + addl %ecx, %eax + movd %xmm10, %ecx + paddq %xmm3, %xmm6 + movl %eax, %r9d + shrl $26, %eax + psrldq $8, %xmm0 + addl %ecx, %eax + movd %xmm6, %ecx + paddq %xmm0, %xmm1 + movl %eax, %esi + andl $67108863, %r9d + movd %xmm1, %r10d + shrl $26, %esi + andl $67108863, %eax + andl $67108863, %edx + addl %ecx, %esi + salq $8, %rax + movl %r9d, %ecx + shrl $18, %r9d + movl %esi, %r8d + shrl $26, %esi + andl $67108863, %r8d + addl %r10d, %esi + orq %r9, %rax + salq $16, %rsi + movq %r8, %r9 + shrl $10, %r8d + salq $26, %rcx + orq %r8, %rsi + salq $34, %r9 + orq %rdx, %rcx + movq %rsi, %r8 + shrq $42, %rsi + movabsq $17592186044415, %rdx + orq %r9, %rax + andq %rbx, %r8 + leaq (%rsi,%rsi,4), %rsi + andq %rdx, %rcx + andq %rdx, %rax + movabsq $-4398046511104, %r10 + addq %rsi, %rcx + movq %rcx, %rsi + shrq $44, %rcx + addq %rcx, %rax + andq %rdx, %rsi + movq %rax, %rcx + shrq $44, %rax + addq %r8, %rax + andq %rdx, %rcx + andq %rax, %rbx + shrq $42, %rax + leaq (%rsi,%rax,4), %rsi + addq %rbx, %r10 + addq %rax, %rsi + movq %rsi, %r8 + shrq $44, %rsi + andq %rdx, %r8 + addq %rcx, %rsi + leaq 5(%r8), %r9 + movq %r9, %r11 + andq %rdx, %r9 + shrq $44, %r11 + addq %rsi, %r11 + movq %r11, %rax + andq %r11, %rdx + shrq $44, %rax + addq %rax, %r10 + movq %r10, %rax + shrq $63, %rax + subq $1, %rax + movq %rax, %rcx + andq %rax, %r9 + andq %rax, %rdx + notq %rcx + andq %r10, %rax + andq %rcx, %r8 + andq %rcx, %rsi + andq %rbx, %rcx + orq %r9, %r8 + orq %rdx, %rsi + orq %rax, %rcx + movq %r8, 0(%rdi) + movq %rsi, 8(%rdi) + movq %rcx, 16(%rdi) + movq -8(%rbp), %rbx + movq %rbp, %rax + subq %rsp, %rax + pxor %xmm15, %xmm15 + pxor %xmm7, %xmm7 + pxor %xmm14, %xmm14 + pxor %xmm6, %xmm6 + pxor %xmm13, %xmm13 + pxor %xmm5, %xmm5 + pxor %xmm12, %xmm12 + pxor %xmm4, %xmm4 + leave + addq $8, %rax + pxor %xmm11, %xmm11 + pxor %xmm3, %xmm3 + pxor %xmm10, %xmm10 + pxor %xmm2, %xmm2 + pxor %xmm9, %xmm9 + pxor %xmm1, %xmm1 + pxor %xmm8, %xmm8 + pxor %xmm0, %xmm0 + ret +.size _gcry_poly1305_amd64_sse2_blocks,.-_gcry_poly1305_amd64_sse2_blocks; + +#endif diff --git a/cipher/poly1305.c b/cipher/poly1305.c index 472ae42..cd1902a 100644 --- a/cipher/poly1305.c +++ b/cipher/poly1305.c @@ -38,6 +38,25 @@ static const char *selftest (void); +#ifdef POLY1305_USE_SSE2 + +void _gcry_poly1305_amd64_sse2_init_ext(void *state, const poly1305_key_t *key); +unsigned int _gcry_poly1305_amd64_sse2_finish_ext(void *state, const byte *m, + size_t remaining, + byte mac[16]); +unsigned int _gcry_poly1305_amd64_sse2_blocks(void *ctx, const byte *m, + size_t bytes); + +static const poly1305_ops_t poly1305_amd64_sse2_ops = { + POLY1305_SSE2_BLOCKSIZE, + _gcry_poly1305_amd64_sse2_init_ext, + _gcry_poly1305_amd64_sse2_blocks, + _gcry_poly1305_amd64_sse2_finish_ext +}; + +#endif + + #ifdef HAVE_U64_TYPEDEF /* Reference unoptimized poly1305 implementation using 32 bit * 32 bit = 64 bit @@ -612,7 +631,11 @@ _gcry_poly1305_init (poly1305_context_t * ctx, const byte * key, if (selftest_failed) return GPG_ERR_SELFTEST_FAILED; +#ifdef POLY1305_USE_SSE2 + ctx->ops = &poly1305_amd64_sse2_ops; +#else ctx->ops = &poly1305_default_ops; +#endif buf_cpy (keytmp.b, key, POLY1305_KEYLEN); poly1305_init (ctx, &keytmp); diff --git a/configure.ac b/configure.ac index 3a0fd52..4dc36d5 100644 --- a/configure.ac +++ b/configure.ac @@ -1821,6 +1821,13 @@ if test "$found" = "1" ; then esac fi +case "${host}" in + x86_64-*-*) + # Build with the assembly implementation + GCRYPT_CIPHERS="$GCRYPT_CIPHERS poly1305-sse2-amd64.lo" + ;; +esac + LIST_MEMBER(dsa, $enabled_pubkey_ciphers) if test "$found" = "1" ; then GCRYPT_PUBKEY_CIPHERS="$GCRYPT_PUBKEY_CIPHERS dsa.lo" ----------------------------------------------------------------------- Summary of changes: cipher/Makefile.am | 3 +- ...hacha20-ssse3-amd64.S => chacha20-sse2-amd64.S} | 226 +++-- cipher/chacha20.c | 18 + cipher/poly1305-avx2-amd64.S | 954 ++++++++++++++++++ cipher/poly1305-internal.h | 45 +- cipher/poly1305-sse2-amd64.S | 1035 ++++++++++++++++++++ cipher/poly1305.c | 49 + configure.ac | 9 + doc/gcrypt.texi | 42 +- 9 files changed, 2271 insertions(+), 110 deletions(-) copy cipher/{chacha20-ssse3-amd64.S => chacha20-sse2-amd64.S} (78%) create mode 100644 cipher/poly1305-avx2-amd64.S create mode 100644 cipher/poly1305-sse2-amd64.S hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Mon May 19 09:47:06 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 19 May 2014 09:47:06 +0200 Subject: [git] GnuPG - branch, master, updated. gnupg-2.1.0beta3-425-g9e1c99f 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 9e1c99f8009f056c39a7465b91912c136b248e8f (commit) via 45f15b2d767d4068f79fd5b123e9eeae08a0616d (commit) from d2d9d4fb60e3f2160af6252335364d3aac4b7d17 (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 9e1c99f8009f056c39a7465b91912c136b248e8f Author: Werner Koch Date: Mon May 19 09:48:42 2014 +0200 dirmngr: Print certificates on failed TLS verification. * dirmngr/ks-engine-hkp.c (cert_log_cb): New. (send_request): Set callback. -- We use the KSBA functions here because we have them anyway in Dirmngr. diff --git a/dirmngr/ks-engine-hkp.c b/dirmngr/ks-engine-hkp.c index 3c25953..0f0baab 100644 --- a/dirmngr/ks-engine-hkp.c +++ b/dirmngr/ks-engine-hkp.c @@ -873,6 +873,40 @@ ks_hkp_housekeeping (time_t curtime) } +/* Callback to print infos about the TLS certificates. */ +static void +cert_log_cb (http_session_t sess, gpg_error_t err, + const char *hostname, const void **certs, size_t *certlens) +{ + ksba_cert_t cert; + size_t n; + + (void)sess; + + if (!err) + return; /* No error - no need to log anything */ + + log_debug ("expected hostname: %s\n", hostname); + for (n=0; certs[n]; n++) + { + err = ksba_cert_new (&cert); + if (!err) + err = ksba_cert_init_from_mem (cert, certs[n], certlens[n]); + if (err) + log_error ("error parsing cert for logging: %s\n", gpg_strerror (err)); + else + { + char textbuf[20]; + snprintf (textbuf, sizeof textbuf, "server[%u]", (unsigned int)n); + dump_cert (textbuf, cert); + } + + ksba_cert_release (cert); + } +} + + + /* Send an HTTP request. On success returns an estream object at R_FP. HOSTPORTSTR is only used for diagnostics. If HTTPHOST is not NULL it will be used as HTTP "Host" header. If POST_CB is not @@ -896,6 +930,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr, err = http_session_new (&session, NULL); if (err) goto leave; + http_session_set_log_cb (session, cert_log_cb); once_more: err = http_open (&http, commit 45f15b2d767d4068f79fd5b123e9eeae08a0616d Author: Werner Koch Date: Mon May 19 09:47:18 2014 +0200 http: Add callback to help logging of server certificates. * common/http.c (http_session_s): Add field cert_log_cb. (http_session_set_log_cb): New. (http_verify_server_credentials): Call callback. diff --git a/common/http.c b/common/http.c index 8a1ad67..4fc89d7 100644 --- a/common/http.c +++ b/common/http.c @@ -234,10 +234,12 @@ struct http_session_s } verify; char *servername; /* Malloced server name. */ #endif /*HTTP_USE_GNUTLS*/ + /* A callback function to log details of TLS certifciates. */ + void (*cert_log_cb) (http_session_t, gpg_error_t, const char *, + const void **, size_t *); }; - /* An object to save header lines. */ struct header_s { @@ -644,6 +646,18 @@ http_session_ref (http_session_t sess) } +void +http_session_set_log_cb (http_session_t sess, + void (*cb)(http_session_t, gpg_error_t, + const char *hostname, + const void **certs, size_t *certlens)) +{ + sess->cert_log_cb = cb; +} + + + + /* Start a HTTP retrieval and on success store at R_HD a context pointer for completing the request and to wait for the response. If HTTPHOST is not NULL it is used hor the Host header instead of a @@ -2497,24 +2511,6 @@ http_verify_server_credentials (http_session_t sess) return err; } - /* log_debug ("Server sent %u certs\n", certlistlen); */ - /* { */ - /* int i; */ - /* char fname[50]; */ - /* FILE *fp; */ - - /* for (i=0; i < certlistlen; i++) */ - /* { */ - /* snprintf (fname, sizeof fname, "xc_%d.der", i); */ - /* fp = fopen (fname, "wb"); */ - /* if (!fp) */ - /* log_fatal ("Failed to create '%s'\n", fname); */ - /* if (fwrite (certlist[i].data, certlist[i].size, 1, fp) != 1) */ - /* log_fatal ("Error writing to '%s'\n", fname); */ - /* fclose (fp); */ - /* } */ - /* } */ - rc = gnutls_x509_crt_init (&cert); if (rc < 0) { @@ -2536,14 +2532,31 @@ http_verify_server_credentials (http_session_t sess) if (!gnutls_x509_crt_check_hostname (cert, hostname)) { log_error ("%s: %s\n", errprefix, "hostname does not match"); - log_info ("(expected '%s')\n", hostname); if (!err) err = gpg_error (GPG_ERR_GENERAL); } gnutls_x509_crt_deinit (cert); + if (!err) sess->verify.rc = 0; + + if (sess->cert_log_cb) + { + const void *bufarr[10]; + size_t buflenarr[10]; + size_t n; + + for (n = 0; n < certlistlen && n < DIM (bufarr)-1; n++) + { + bufarr[n] = certlist[n].data; + buflenarr[n] = certlist[n].size; + } + bufarr[n] = NULL; + buflenarr[n] = 0; + sess->cert_log_cb (sess, err, hostname, bufarr, buflenarr); + } + return err; #else /*!HTTP_USE_GNUTLS*/ (void)sess; diff --git a/common/http.h b/common/http.h index acfdc0f..416e220 100644 --- a/common/http.h +++ b/common/http.h @@ -98,6 +98,11 @@ gpg_error_t http_session_new (http_session_t *r_session, http_session_t http_session_ref (http_session_t sess); void http_session_release (http_session_t sess); +void http_session_set_log_cb (http_session_t sess, + void (*cb)(http_session_t, gpg_error_t, + const char *, + const void **, size_t *)); + gpg_error_t http_parse_uri (parsed_uri_t *ret_uri, const char *uri, int no_scheme_check); ----------------------------------------------------------------------- Summary of changes: common/http.c | 53 +++++++++++++++++++++++++++++------------------ common/http.h | 5 +++++ dirmngr/ks-engine-hkp.c | 35 +++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 20 deletions(-) hooks/post-receive -- The GNU Privacy Guard http://git.gnupg.org From cvs at cvs.gnupg.org Tue May 20 21:10:00 2014 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Tue, 20 May 2014 21:10:00 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-81-g994c758 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 994c758d8f5471c7e9c38c2834742cca2502d35f (commit) from bf4943932dae95a0573b63bf32a9b9acd5a6ddf3 (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 994c758d8f5471c7e9c38c2834742cca2502d35f Author: Jussi Kivilinna Date: Tue May 20 20:35:51 2014 +0300 Fix ARM assembly when building __PIC__ * cipher/camellia-arm.S (GET_DATA_POINTER): New. (_gcry_camellia_arm_encrypt_block): Use GET_DATA_POINTER. (_gcry_camellia_arm_decrypt_block): Ditto. * cipher/cast5-arm.S (GET_DATA_POINTER): New. (_gcry_cast5_arm_encrypt_block, _gcry_cast5_arm_decrypt_block) (_gcry_cast5_arm_enc_blk2, _gcry_cast5_arm_dec_blk2): Use GET_DATA_POINTER. * cipher/rijndael-arm.S (GET_DATA_POINTER): New. (_gcry_aes_arm_encrypt_block, _gcry_aes_arm_decrypt_block): Use GET_DATA_POINTER. * cipher/sha1-armv7-neon.S (GET_DATA_POINTER): New. (.LK_VEC): Move from .text to .data section. (_gcry_sha1_transform_armv7_neon): Use GET_DATA_POINTER. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/camellia-arm.S b/cipher/camellia-arm.S index 255a246..a3d87d1 100644 --- a/cipher/camellia-arm.S +++ b/cipher/camellia-arm.S @@ -28,6 +28,19 @@ .syntax unified .arm +#ifdef __PIC__ +# define GET_DATA_POINTER(reg, name, rtmp) \ + ldr reg, 1f; \ + ldr rtmp, 2f; \ + b 3f; \ + 1: .word _GLOBAL_OFFSET_TABLE_-(3f+8); \ + 2: .word name(GOT); \ + 3: add reg, pc, reg; \ + ldr reg, [reg, rtmp]; +#else +# define GET_DATA_POINTER(reg, name, rtmp) ldr reg, =name +#endif + /* struct camellia_ctx: */ #define key_table 0 @@ -261,7 +274,7 @@ _gcry_camellia_arm_encrypt_block: */ push {%r1, %r4-%r11, %ip, %lr}; - ldr RTAB1, =.Lcamellia_sp1110; + GET_DATA_POINTER(RTAB1, .Lcamellia_sp1110, RTAB3); mov RMASK, #0xff; add RTAB3, RTAB1, #(2 * 4); push {%r3}; @@ -309,7 +322,7 @@ _gcry_camellia_arm_decrypt_block: */ push {%r1, %r4-%r11, %ip, %lr}; - ldr RTAB1, =.Lcamellia_sp1110; + GET_DATA_POINTER(RTAB1, .Lcamellia_sp1110, RTAB3); mov RMASK, #0xff; add RTAB3, RTAB1, #(2 * 4); mov RMASK, RMASK, lsl#4 /* byte mask */ diff --git a/cipher/cast5-arm.S b/cipher/cast5-arm.S index 57c89b7..76ddd2e 100644 --- a/cipher/cast5-arm.S +++ b/cipher/cast5-arm.S @@ -30,6 +30,19 @@ .extern _gcry_cast5_s1to4; +#ifdef __PIC__ +# define GET_DATA_POINTER(reg, name, rtmp) \ + ldr reg, 1f; \ + ldr rtmp, 2f; \ + b 3f; \ + 1: .word _GLOBAL_OFFSET_TABLE_-(3f+8); \ + 2: .word name(GOT); \ + 3: add reg, pc, reg; \ + ldr reg, [reg, rtmp]; +#else +# define GET_DATA_POINTER(reg, name, rtmp) ldr reg, =name +#endif + /* structure of crypto context */ #define Km 0 #define Kr (Km + (16 * 4)) @@ -260,7 +273,7 @@ _gcry_cast5_arm_encrypt_block: */ push {%r1, %r4-%r11, %ip, %lr}; - ldr Rs1, =_gcry_cast5_s1to4; + GET_DATA_POINTER(Rs1, _gcry_cast5_s1to4, Rs2); mov RMASK, #(0xff << 2); add Rs2, Rs1, #(0x100*4); add Rs3, Rs1, #(0x100*4*2); @@ -306,7 +319,7 @@ _gcry_cast5_arm_decrypt_block: */ push {%r1, %r4-%r11, %ip, %lr}; - ldr Rs1, =_gcry_cast5_s1to4; + GET_DATA_POINTER(Rs1, _gcry_cast5_s1to4, Rs2); mov RMASK, #(0xff << 2); add Rs2, Rs1, #(0x100 * 4); add Rs3, Rs1, #(0x100 * 4 * 2); @@ -500,7 +513,7 @@ _gcry_cast5_arm_enc_blk2: */ push {%lr}; - ldr Rs1, =_gcry_cast5_s1to4; + GET_DATA_POINTER(Rs1, _gcry_cast5_s1to4, Rs2); mov RMASK, #(0xff << 2); add Rs2, Rs1, #(0x100 * 4); @@ -631,7 +644,7 @@ _gcry_cast5_arm_dec_blk2: * [RR0, RL0], [RR1, RL1]: dst */ - ldr Rs1, =_gcry_cast5_s1to4; + GET_DATA_POINTER(Rs1, _gcry_cast5_s1to4, Rs2); mov RMASK, #(0xff << 2); add Rs2, Rs1, #(0x100 * 4); diff --git a/cipher/rijndael-arm.S b/cipher/rijndael-arm.S index cea8c51..6004ce8 100644 --- a/cipher/rijndael-arm.S +++ b/cipher/rijndael-arm.S @@ -28,6 +28,19 @@ .syntax unified .arm +#ifdef __PIC__ +# define GET_DATA_POINTER(reg, name, rtmp) \ + ldr reg, 1f; \ + ldr rtmp, 2f; \ + b 3f; \ + 1: .word _GLOBAL_OFFSET_TABLE_-(3f+8); \ + 2: .word name(GOT); \ + 3: add reg, pc, reg; \ + ldr reg, [reg, rtmp]; +#else +# define GET_DATA_POINTER(reg, name, rtmp) ldr reg, =name +#endif + /* register macros */ #define CTX %r0 #define RTAB %lr @@ -249,7 +262,7 @@ _gcry_aes_arm_encrypt_block: 2: sub %sp, #16; - ldr RTAB, =.LtableE0; + GET_DATA_POINTER(RTAB, .LtableE0, RMASK); str %r1, [%sp, #4]; /* dst */ mov RMASK, #0xff; @@ -503,7 +516,7 @@ _gcry_aes_arm_decrypt_block: 2: sub %sp, #16; - ldr RTAB, =.LtableD0; + GET_DATA_POINTER(RTAB, .LtableD0, RMASK); mov RMASK, #0xff; str %r1, [%sp, #4]; /* dst */ diff --git a/cipher/sha1-armv7-neon.S b/cipher/sha1-armv7-neon.S index 0c19025..95b677d 100644 --- a/cipher/sha1-armv7-neon.S +++ b/cipher/sha1-armv7-neon.S @@ -26,12 +26,25 @@ defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \ defined(HAVE_GCC_INLINE_ASM_NEON) && defined(USE_SHA1) -.text +.data .syntax unified .fpu neon .arm +#ifdef __PIC__ +# define GET_DATA_POINTER(reg, name, rtmp) \ + ldr reg, 1f; \ + ldr rtmp, 2f; \ + b 3f; \ + 1: .word _GLOBAL_OFFSET_TABLE_-(3f+8); \ + 2: .word name(GOT); \ + 3: add reg, pc, reg; \ + ldr reg, [reg, rtmp]; +#else +# define GET_DATA_POINTER(reg, name, rtmp) ldr reg, =name +#endif + /* Context structure */ #define state_h0 0 @@ -56,6 +69,8 @@ gcry_sha1_armv7_neon_K_VEC: .LK4: .long K4, K4, K4, K4 +.text + /* Register macros */ #define RSTATE r0 @@ -314,7 +329,7 @@ _gcry_sha1_transform_armv7_neon: vpush {q4-q7}; mov ROLDSTACK, sp; - ldr RK, =.LK_VEC; + GET_DATA_POINTER(RK, .LK_VEC, _a); /* Align stack. */ sub sp, #(16*4); ----------------------------------------------------------------------- Summary of changes: cipher/camellia-arm.S | 17 +++++++++++++++-- cipher/cast5-arm.S | 21 +++++++++++++++++---- cipher/rijndael-arm.S | 17 +++++++++++++++-- cipher/sha1-armv7-neon.S | 19 +++++++++++++++++-- 4 files changed, 64 insertions(+), 10 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Tue May 20 21:11:52 2014 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Tue, 20 May 2014 21:11:52 +0200 Subject: [git] GCRYPT - branch, LIBGCRYPT-1-6-BRANCH, updated. libgcrypt-1.6.1-12-gc76acdc 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, LIBGCRYPT-1-6-BRANCH has been updated via c76acdc1eeea65b5a04c3e044344abb7f7abf8df (commit) from af75f6294f5aad8228241cdc32a883352f2150ea (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 c76acdc1eeea65b5a04c3e044344abb7f7abf8df Author: Jussi Kivilinna Date: Tue May 20 20:35:51 2014 +0300 Fix ARM assembly when building __PIC__ * cipher/camellia-arm.S (GET_DATA_POINTER): New. (_gcry_camellia_arm_encrypt_block): Use GET_DATA_POINTER. (_gcry_camellia_arm_decrypt_block): Ditto. * cipher/cast5-arm.S (GET_DATA_POINTER): New. (_gcry_cast5_arm_encrypt_block, _gcry_cast5_arm_decrypt_block) (_gcry_cast5_arm_enc_blk2, _gcry_cast5_arm_dec_blk2): Use GET_DATA_POINTER. * cipher/rijndael-arm.S (GET_DATA_POINTER): New. (_gcry_aes_arm_encrypt_block, _gcry_aes_arm_decrypt_block): Use GET_DATA_POINTER. -- Signed-off-by: Jussi Kivilinna (cherry picked from commit 994c758d8f5471c7e9c38c2834742cca2502d35f) diff --git a/cipher/camellia-arm.S b/cipher/camellia-arm.S index c30d194..cdeaf8b 100644 --- a/cipher/camellia-arm.S +++ b/cipher/camellia-arm.S @@ -28,6 +28,19 @@ .syntax unified .arm +#ifdef __PIC__ +# define GET_DATA_POINTER(reg, name, rtmp) \ + ldr reg, 1f; \ + ldr rtmp, 2f; \ + b 3f; \ + 1: .word _GLOBAL_OFFSET_TABLE_-(3f+8); \ + 2: .word name(GOT); \ + 3: add reg, pc, reg; \ + ldr reg, [reg, rtmp]; +#else +# define GET_DATA_POINTER(reg, name, rtmp) ldr reg, =name +#endif + /* struct camellia_ctx: */ #define key_table 0 @@ -261,7 +274,7 @@ _gcry_camellia_arm_encrypt_block: */ push {%r1, %r4-%r11, %ip, %lr}; - ldr RTAB1, =.Lcamellia_sp1110; + GET_DATA_POINTER(RTAB1, .Lcamellia_sp1110, RTAB3); mov RMASK, #0xff; add RTAB3, RTAB1, #(2 * 4); push {%r3}; @@ -309,7 +322,7 @@ _gcry_camellia_arm_decrypt_block: */ push {%r1, %r4-%r11, %ip, %lr}; - ldr RTAB1, =.Lcamellia_sp1110; + GET_DATA_POINTER(RTAB1, .Lcamellia_sp1110, RTAB3); mov RMASK, #0xff; add RTAB3, RTAB1, #(2 * 4); mov RMASK, RMASK, lsl#4 /* byte mask */ diff --git a/cipher/cast5-arm.S b/cipher/cast5-arm.S index ce7fa93..db96db4 100644 --- a/cipher/cast5-arm.S +++ b/cipher/cast5-arm.S @@ -30,6 +30,19 @@ .extern _gcry_cast5_s1to4; +#ifdef __PIC__ +# define GET_DATA_POINTER(reg, name, rtmp) \ + ldr reg, 1f; \ + ldr rtmp, 2f; \ + b 3f; \ + 1: .word _GLOBAL_OFFSET_TABLE_-(3f+8); \ + 2: .word name(GOT); \ + 3: add reg, pc, reg; \ + ldr reg, [reg, rtmp]; +#else +# define GET_DATA_POINTER(reg, name, rtmp) ldr reg, =name +#endif + /* structure of crypto context */ #define Km 0 #define Kr (Km + (16 * 4)) @@ -260,7 +273,7 @@ _gcry_cast5_arm_encrypt_block: */ push {%r1, %r4-%r11, %ip, %lr}; - ldr Rs1, =_gcry_cast5_s1to4; + GET_DATA_POINTER(Rs1, _gcry_cast5_s1to4, Rs2); mov RMASK, #(0xff << 2); add Rs2, Rs1, #(0x100*4); add Rs3, Rs1, #(0x100*4*2); @@ -306,7 +319,7 @@ _gcry_cast5_arm_decrypt_block: */ push {%r1, %r4-%r11, %ip, %lr}; - ldr Rs1, =_gcry_cast5_s1to4; + GET_DATA_POINTER(Rs1, _gcry_cast5_s1to4, Rs2); mov RMASK, #(0xff << 2); add Rs2, Rs1, #(0x100 * 4); add Rs3, Rs1, #(0x100 * 4 * 2); @@ -500,7 +513,7 @@ _gcry_cast5_arm_enc_blk2: */ push {%lr}; - ldr Rs1, =_gcry_cast5_s1to4; + GET_DATA_POINTER(Rs1, _gcry_cast5_s1to4, Rs2); mov RMASK, #(0xff << 2); add Rs2, Rs1, #(0x100 * 4); @@ -631,7 +644,7 @@ _gcry_cast5_arm_dec_blk2: * [RR0, RL0], [RR1, RL1]: dst */ - ldr Rs1, =_gcry_cast5_s1to4; + GET_DATA_POINTER(Rs1, _gcry_cast5_s1to4, Rs2); mov RMASK, #(0xff << 2); add Rs2, Rs1, #(0x100 * 4); diff --git a/cipher/rijndael-arm.S b/cipher/rijndael-arm.S index 22c350c..421c3b4 100644 --- a/cipher/rijndael-arm.S +++ b/cipher/rijndael-arm.S @@ -28,6 +28,19 @@ .syntax unified .arm +#ifdef __PIC__ +# define GET_DATA_POINTER(reg, name, rtmp) \ + ldr reg, 1f; \ + ldr rtmp, 2f; \ + b 3f; \ + 1: .word _GLOBAL_OFFSET_TABLE_-(3f+8); \ + 2: .word name(GOT); \ + 3: add reg, pc, reg; \ + ldr reg, [reg, rtmp]; +#else +# define GET_DATA_POINTER(reg, name, rtmp) ldr reg, =name +#endif + /* register macros */ #define CTX %r0 #define RTAB %lr @@ -249,7 +262,7 @@ _gcry_aes_arm_encrypt_block: 2: sub %sp, #16; - ldr RTAB, =.LtableE0; + GET_DATA_POINTER(RTAB, .LtableE0, RMASK); str %r1, [%sp, #4]; /* dst */ mov RMASK, #0xff; @@ -503,7 +516,7 @@ _gcry_aes_arm_decrypt_block: 2: sub %sp, #16; - ldr RTAB, =.LtableD0; + GET_DATA_POINTER(RTAB, .LtableD0, RMASK); mov RMASK, #0xff; str %r1, [%sp, #4]; /* dst */ ----------------------------------------------------------------------- Summary of changes: cipher/camellia-arm.S | 17 +++++++++++++++-- cipher/cast5-arm.S | 21 +++++++++++++++++---- cipher/rijndael-arm.S | 17 +++++++++++++++-- 3 files changed, 47 insertions(+), 8 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Wed May 21 07:28:35 2014 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Wed, 21 May 2014 07:28:35 +0200 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-83-gf14fb5b 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 f14fb5b427b5159fcd9603d2b3cde936889cf430 (commit) via beb901575f0d6cd6a0a27506ebea9a725754d0cc (commit) from 994c758d8f5471c7e9c38c2834742cca2502d35f (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 f14fb5b427b5159fcd9603d2b3cde936889cf430 Author: Jussi Kivilinna Date: Wed May 21 08:30:30 2014 +0300 tests: add larger test-vectors for hash algorithms * tests/basic.c (check_digests): Add large test-vectors for MD5, SHA1, SHA224, SHA256, SHA384, RMD160, CRC32, TIGER1, WHIRLPOOL and GOSTR3411_94. -- Signed-off-by: Jussi Kivilinna diff --git a/tests/basic.c b/tests/basic.c index 2be6432..875b36c 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -4526,6 +4526,16 @@ check_digests (void) "\x90\x01\x50\x98\x3C\xD2\x4F\xB0\xD6\x96\x3F\x7D\x28\xE1\x7F\x72" }, { GCRY_MD_MD5, "message digest", "\xF9\x6B\x69\x7D\x7C\xB7\x93\x8D\x52\x5A\x2F\x31\xAA\xF1\x61\xD0" }, + { GCRY_MD_MD5, + "Libgcrypt is free software; you can redistribute it and/or modif" + "y it under the terms of the GNU Lesser general Public License as" + " published by the Free Software Foundation; either version 2.1 o" + "f the License, or (at your option) any later version.\nLibgcrypt" + " is distributed in the hope that it will be useful, but WITHOUT " + "ANY WARRANTY; without even the implied warranty of MERCHANTABILI" + "TY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser Gene" + "ral Public License for more details.", + "\xc4\x1a\x5c\x0b\x44\x5f\xba\x1a\xda\xbc\xc0\x38\x0e\x0c\x9e\x33" }, { GCRY_MD_SHA1, "abc", "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E" "\x25\x71\x78\x50\xC2\x6C\x9C\xD0\xD8\x9D" }, @@ -4536,6 +4546,17 @@ check_digests (void) { GCRY_MD_SHA1, "!" /* kludge for "a"*1000000 */ , "\x34\xAA\x97\x3C\xD4\xC4\xDA\xA4\xF6\x1E" "\xEB\x2B\xDB\xAD\x27\x31\x65\x34\x01\x6F" }, + { GCRY_MD_SHA1, + "Libgcrypt is free software; you can redistribute it and/or modif" + "y it under the terms of the GNU Lesser general Public License as" + " published by the Free Software Foundation; either version 2.1 o" + "f the License, or (at your option) any later version.\nLibgcrypt" + " is distributed in the hope that it will be useful, but WITHOUT " + "ANY WARRANTY; without even the implied warranty of MERCHANTABILI" + "TY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser Gene" + "ral Public License for more details.", + "\xf5\xd9\xcb\x66\x91\xb4\x7a\x7c\x60\x35\xe2\x1c\x38\x26\x52\x13" + "\x8e\xd5\xe5\xdf" }, /* From RFC3874 */ { GCRY_MD_SHA224, "abc", "\x23\x09\x7d\x22\x34\x05\xd8\x22\x86\x42\xa4\x77\xbd\xa2\x55\xb3" @@ -4547,6 +4568,17 @@ check_digests (void) { GCRY_MD_SHA224, "!", "\x20\x79\x46\x55\x98\x0c\x91\xd8\xbb\xb4\xc1\xea\x97\x61\x8a\x4b" "\xf0\x3f\x42\x58\x19\x48\xb2\xee\x4e\xe7\xad\x67" }, + { GCRY_MD_SHA224, + "Libgcrypt is free software; you can redistribute it and/or modif" + "y it under the terms of the GNU Lesser general Public License as" + " published by the Free Software Foundation; either version 2.1 o" + "f the License, or (at your option) any later version.\nLibgcrypt" + " is distributed in the hope that it will be useful, but WITHOUT " + "ANY WARRANTY; without even the implied warranty of MERCHANTABILI" + "TY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser Gene" + "ral Public License for more details.", + "\x80\xf0\x60\x79\xb0\xe9\x65\xab\x8a\x76\xbf\x6e\x88\x64\x75\xe7" + "\xfd\xf0\xc2\x4c\xf6\xf2\xa6\x01\xed\x50\x71\x08" }, { GCRY_MD_SHA256, "abc", "\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23" "\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad" }, @@ -4557,10 +4589,33 @@ check_digests (void) { GCRY_MD_SHA256, "!", "\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67" "\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0" }, + { GCRY_MD_SHA256, + "Libgcrypt is free software; you can redistribute it and/or modif" + "y it under the terms of the GNU Lesser general Public License as" + " published by the Free Software Foundation; either version 2.1 o" + "f the License, or (at your option) any later version.\nLibgcrypt" + " is distributed in the hope that it will be useful, but WITHOUT " + "ANY WARRANTY; without even the implied warranty of MERCHANTABILI" + "TY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser Gene" + "ral Public License for more details.", + "\xb0\x18\x70\x67\xb8\xac\x68\x50\xec\x95\x43\x77\xb5\x44\x5b\x0f" + "\x2e\xbd\x40\xc9\xdc\x2a\x2c\x33\x8b\x53\xeb\x3e\x9e\x01\xd7\x02" }, { GCRY_MD_SHA384, "abc", "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07" "\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed" "\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7" }, + { GCRY_MD_SHA384, + "Libgcrypt is free software; you can redistribute it and/or modif" + "y it under the terms of the GNU Lesser general Public License as" + " published by the Free Software Foundation; either version 2.1 o" + "f the License, or (at your option) any later version.\nLibgcrypt" + " is distributed in the hope that it will be useful, but WITHOUT " + "ANY WARRANTY; without even the implied warranty of MERCHANTABILI" + "TY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser Gene" + "ral Public License for more details.", + "\xe4\x6d\xb4\x28\x33\x77\x99\x49\x94\x0f\xcf\x87\xc2\x2f\x30\xd6" + "\x06\x24\x82\x9d\x80\x64\x8a\x07\xa1\x20\x8f\x5f\xf3\x85\xb3\xaa" + "\x39\xb8\x61\x00\xfc\x7f\x18\xc6\x82\x23\x4b\x45\xfa\xf1\xbc\x69" }, { GCRY_MD_SHA512, "abc", "\xDD\xAF\x35\xA1\x93\x61\x7A\xBA\xCC\x41\x73\x49\xAE\x20\x41\x31" "\x12\xE6\xFA\x4E\x89\xA9\x7E\xA2\x0A\x9E\xEE\xE6\x4B\x55\xD3\x9A" @@ -4591,8 +4646,29 @@ check_digests (void) { GCRY_MD_RMD160, "message digest", "\x5d\x06\x89\xef\x49\xd2\xfa\xe5\x72\xb8" "\x81\xb1\x23\xa8\x5f\xfa\x21\x59\x5f\x36" }, + { GCRY_MD_RMD160, + "Libgcrypt is free software; you can redistribute it and/or modif" + "y it under the terms of the GNU Lesser general Public License as" + " published by the Free Software Foundation; either version 2.1 o" + "f the License, or (at your option) any later version.\nLibgcrypt" + " is distributed in the hope that it will be useful, but WITHOUT " + "ANY WARRANTY; without even the implied warranty of MERCHANTABILI" + "TY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser Gene" + "ral Public License for more details.", + "\x06\x6d\x3c\x4e\xc9\xba\x89\x75\x16\x90\x96\x4e\xfd\x43\x07\xde" + "\x04\xca\x69\x6b" }, { GCRY_MD_CRC32, "", "\x00\x00\x00\x00" }, { GCRY_MD_CRC32, "foo", "\x8c\x73\x65\x21" }, + { GCRY_MD_CRC32, + "Libgcrypt is free software; you can redistribute it and/or modif" + "y it under the terms of the GNU Lesser general Public License as" + " published by the Free Software Foundation; either version 2.1 o" + "f the License, or (at your option) any later version.\nLibgcrypt" + " is distributed in the hope that it will be useful, but WITHOUT " + "ANY WARRANTY; without even the implied warranty of MERCHANTABILI" + "TY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser Gene" + "ral Public License for more details.", + "\x4A\x53\x7D\x67" }, { GCRY_MD_CRC32_RFC1510, "", "\x00\x00\x00\x00" }, { GCRY_MD_CRC32_RFC1510, "foo", "\x73\x32\xbc\x33" }, { GCRY_MD_CRC32_RFC1510, "test0123456789", "\xb8\x3e\x88\xd6" }, @@ -4680,6 +4756,17 @@ check_digests (void) { GCRY_MD_TIGER1, "!", "\x6D\xB0\xE2\x72\x9C\xBE\xAD\x93\xD7\x15\xC6\xA7" "\xD3\x63\x02\xE9\xB3\xCE\xE0\xD2\xBC\x31\x4B\x41" }, + { GCRY_MD_TIGER1, + "Libgcrypt is free software; you can redistribute it and/or modif" + "y it under the terms of the GNU Lesser general Public License as" + " published by the Free Software Foundation; either version 2.1 o" + "f the License, or (at your option) any later version.\nLibgcrypt" + " is distributed in the hope that it will be useful, but WITHOUT " + "ANY WARRANTY; without even the implied warranty of MERCHANTABILI" + "TY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser Gene" + "ral Public License for more details.", + "\x60\xee\xdf\x95\x39\xc8\x44\x94\x64\xdc\xdf\x3d\x2e\x1c\xe5\x79" + "\x6a\x95\xbd\x30\x68\x8c\x7e\xb8" }, { GCRY_MD_TIGER2, "", "\x44\x41\xBE\x75\xF6\x01\x87\x73\xC2\x06\xC2\x27" @@ -4741,6 +4828,19 @@ check_digests (void) "\x29\x05\x7F\xD8\x6B\x20\xBF\xD6\x2D\xEC\xA0\xF1\xCC\xEA\x4A\xF5" "\x1F\xC1\x54\x90\xED\xDC\x47\xAF\x32\xBB\x2B\x66\xC3\x4F\xF9\xAD" "\x8C\x60\x08\xAD\x67\x7F\x77\x12\x69\x53\xB2\x26\xE4\xED\x8B\x01" }, + { GCRY_MD_WHIRLPOOL, + "Libgcrypt is free software; you can redistribute it and/or modif" + "y it under the terms of the GNU Lesser general Public License as" + " published by the Free Software Foundation; either version 2.1 o" + "f the License, or (at your option) any later version.\nLibgcrypt" + " is distributed in the hope that it will be useful, but WITHOUT " + "ANY WARRANTY; without even the implied warranty of MERCHANTABILI" + "TY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser Gene" + "ral Public License for more details.", + "\xcd\x4a\xa4\xaf\xf6\x7f\xec\xce\xbb\x6c\xdf\x91\x96\xe1\xf3\xf6" + "\x78\xe2\x8e\x3a\x76\xcf\x06\xc7\xa1\x20\x7b\x81\x32\x60\xf7\x8e" + "\x68\x19\x62\x33\x4f\xe5\x0a\x24\xfb\x9e\x74\x03\x74\xe4\x61\x29" + "\x6f\xb3\x13\xe6\x7e\xc2\x88\x99\x9e\xfb\xe7\x9d\x11\x30\x89\xd2" }, { GCRY_MD_GOSTR3411_94, "This is message, length=32 bytes", "\xB1\xC4\x66\xD3\x75\x19\xB8\x2E\x83\x19\x81\x9F\xF3\x25\x95\xE0" @@ -4757,6 +4857,17 @@ check_digests (void) "!", "\x5C\x00\xCC\xC2\x73\x4C\xDD\x33\x32\xD3\xD4\x74\x95\x76\xE3\xC1" "\xA7\xDB\xAF\x0E\x7E\xA7\x4E\x9F\xA6\x02\x41\x3C\x90\xA1\x29\xFA" }, + { GCRY_MD_GOSTR3411_94, + "Libgcrypt is free software; you can redistribute it and/or modif" + "y it under the terms of the GNU Lesser general Public License as" + " published by the Free Software Foundation; either version 2.1 o" + "f the License, or (at your option) any later version.\nLibgcrypt" + " is distributed in the hope that it will be useful, but WITHOUT " + "ANY WARRANTY; without even the implied warranty of MERCHANTABILI" + "TY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser Gene" + "ral Public License for more details.", + "\x00\x0c\x85\xc8\x54\xd2\x9a\x6e\x47\x2e\xff\xa4\xa2\xe7\xd0\x2e" + "\x8a\xcc\x14\x53\xb4\x87\xc8\x5c\x95\x9a\x3e\x85\x8c\x7d\x6e\x0c" }, { GCRY_MD_STRIBOG512, "012345678901234567890123456789012345678901234567890123456789012", "\x1b\x54\xd0\x1a\x4a\xf5\xb9\xd5\xcc\x3d\x86\xd6\x8d\x28\x54\x62" commit beb901575f0d6cd6a0a27506ebea9a725754d0cc Author: Jussi Kivilinna Date: Wed May 21 08:30:30 2014 +0300 sha512: fix ARM/NEON implementation * cipher/sha512-armv7-neon.S (_gcry_sha512_transform_armv7_neon): Byte-swap RW67q and RW1011q correctly in multi-block loop. * tests/basic.c (check_digests): Add large test vector for SHA512. -- Patch fixes bug introduced to multi-block processing by commit df629ba53a6, "Improve performance of SHA-512/ARM/NEON implementation". Patch also adds multi-block test vector for SHA-512. Signed-off-by: Jussi Kivilinna diff --git a/cipher/sha512-armv7-neon.S b/cipher/sha512-armv7-neon.S index bb2cbb4..a9d1272 100644 --- a/cipher/sha512-armv7-neon.S +++ b/cipher/sha512-armv7-neon.S @@ -361,8 +361,8 @@ _gcry_sha512_transform_armv7_neon: rounds2_64_79(RE, RF, RG, RH, RA, RB, RC, RD, RW12, RW13, vadd_rg_RT0, RE, vadd_rg_RT1, RE); rounds2_64_79(RC, RD, RE, RF, RG, RH, RA, RB, RW14, RW15, vadd_rg_RT0, RC, vadd_rg_RT1, RC); #ifdef __ARMEL__ - vrev64.8 RW67q, RW67q; vrev64.8 RW89q, RW89q; + vrev64.8 RW1011q, RW1011q; #endif vld1.64 {RW12-RW15}, [%r1]!; vadd_rg_RT0(RA); diff --git a/tests/basic.c b/tests/basic.c index 9740919..2be6432 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -4566,6 +4566,19 @@ check_digests (void) "\x12\xE6\xFA\x4E\x89\xA9\x7E\xA2\x0A\x9E\xEE\xE6\x4B\x55\xD3\x9A" "\x21\x92\x99\x2A\x27\x4F\xC1\xA8\x36\xBA\x3C\x23\xA3\xFE\xEB\xBD" "\x45\x4D\x44\x23\x64\x3C\xE8\x0E\x2A\x9A\xC9\x4F\xA5\x4C\xA4\x9F" }, + { GCRY_MD_SHA512, + "Libgcrypt is free software; you can redistribute it and/or modif" + "y it under the terms of the GNU Lesser general Public License as" + " published by the Free Software Foundation; either version 2.1 o" + "f the License, or (at your option) any later version.\nLibgcrypt" + " is distributed in the hope that it will be useful, but WITHOUT " + "ANY WARRANTY; without even the implied warranty of MERCHANTABILI" + "TY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser Gene" + "ral Public License for more details.", + "\x72\x8c\xde\xd8\xe4\xd7\xb6\xa5\x0f\xde\x6b\x4d\x33\xaf\x15\x19" + "\xdd\xec\x62\x0f\xf7\x1a\x1e\x10\x32\x05\x02\xa6\xb0\x1f\x70\x37" + "\xbc\xd7\x15\xed\x71\x6c\x78\x20\xc8\x54\x87\xd0\x66\x6a\x17\x83" + "\x05\x61\x92\xbe\xcc\x8f\x3b\xbf\x11\x72\x22\x69\x23\x5b\x48\x5c" }, { GCRY_MD_RMD160, "", "\x9c\x11\x85\xa5\xc5\xe9\xfc\x54\x61\x28" "\x08\x97\x7e\xe8\xf5\x48\xb2\x25\x8d\x31" }, ----------------------------------------------------------------------- Summary of changes: cipher/sha512-armv7-neon.S | 2 +- tests/basic.c | 124 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 1 deletion(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org From cvs at cvs.gnupg.org Wed May 21 09:40:11 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 21 May 2014 09:40:11 +0200 Subject: [git] GPGME - branch, master, updated. gpgme-1.4.3-31-g0eca211 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 0eca21113c1d1ab2aea58e1ea21075f472f99c23 (commit) from de6caeed6d6432101c673c35717f152d5facf823 (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 0eca21113c1d1ab2aea58e1ea21075f472f99c23 Author: Werner Koch Date: Wed May 21 09:08:42 2014 +0200 Release 1.5.0. * configure.ac: Change LT version to C22/A11/R0. diff --git a/NEWS b/NEWS index 3eaca19..82d4914 100644 --- a/NEWS +++ b/NEWS @@ -1,18 +1,24 @@ -Noteworthy changes in version 1.5.0 (unreleased) ------------------------------------------------- +Noteworthy changes in version 1.5.0 (2014-05-21) [C23/A12/R0] +------------------------------------------------------------- * On Unices the engine file names are not not anymore hardwired but - located via the envvar PATH. All configuration options to set the - name of the engines for configure run are removed. + located via the envvar PATH. All options to set the name of the + engines for the configure run are removed. * If GPGME finds the gpgconf binary it defaults to using gpg2 or whatever gpgconf tells as name for the OpenPGP engine. If gpgconf is not found, GPGME looks for an engine named "gpg". - * Add feature to use the gpgme I/O subsystem to run arbitrary + * New feature to use the gpgme I/O subsystem to run arbitrary commands. - * Add flag to force encryption without the default compression step. + * New flag to use encryption without the default compression step. + + * New function to access "gpg-conf --list-dirs" + + * New configure option --enable-fixed-path for use by Android. + + * Support ECC algorithms. * Interface changes relative to the 1.4.3 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -34,8 +40,8 @@ Noteworthy changes in version 1.5.0 (unreleased) GPGME_STATUS_KEY_NOT_CREATED NEW. -Noteworthy changes in version 1.4.3 (2013-08-12) ------------------------------------------------- +Noteworthy changes in version 1.4.3 (2013-08-12) [C22/A11/R0] +------------------------------------------------------------- * The default engine names are now taken from the output of gpgconf. If gpgconf is not found the use of gpg 1 is assumed. @@ -52,8 +58,8 @@ Noteworthy changes in version 1.4.3 (2013-08-12) gpgme_data_identify NEW. -Noteworthy changes in version 1.4.2 (2013-05-28) ------------------------------------------------- +Noteworthy changes in version 1.4.2 (2013-05-28) [C21/A10/R0] +------------------------------------------------------------- * Allow symmetric encryption with gpgme_op_encrypt_sign. @@ -66,8 +72,8 @@ Noteworthy changes in version 1.4.2 (2013-05-28) GPGME_PROTOCOL_OPENPGP NEW alias. -Noteworthy changes in version 1.4.1 (2013-05-01) ------------------------------------------------- +Noteworthy changes in version 1.4.1 (2013-05-01) [C20/A9/R1] +------------------------------------------------------------ * Fixed reading of gpg.conf files with excessive use of the group option. @@ -77,8 +83,8 @@ Noteworthy changes in version 1.4.1 (2013-05-01) * Disabled FD passing by default for Apple. -Noteworthy changes in version 1.4.0 (2013-02-26) ------------------------------------------------- +Noteworthy changes in version 1.4.0 (2013-02-26) [C20/A9/R0] +------------------------------------------------------------ * New function gpgme_set_global_flag to help debugging on Android. diff --git a/README b/README index 3b39215..a16a066 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ GPGME - GnuPG Made Easy --------------------------- - Copyright 2004, 2006, 2010, 2012, 2013 g10 Code GmbH + Copyright 2004, 2006, 2010, 2012, 2013, 2014 g10 Code GmbH This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without @@ -46,14 +46,10 @@ Libassuan (>= 2.0.2). For support of the OpenPGP protocol (default), you should use the latest version of GnuPG (>= 1.4) , available at: -ftp://ftp.gnupg.org/gcrypt/gnupg/ -For support of the CMS (Cryptographic Message Syntax) protocol, you +ftp://ftp.gnupg.org/gcrypt/gnupg/. For support of the CMS +(Cryptographic Message Syntax) protocol and lot of other features, you need a GnuPG version >= 2.0. -On some platforms GPGME based applications might hang at certain -operations when using GPGME_PROTOCOL_CMS. A workaround for this -problem is to build with the configure option --disable-fd-passing. - For building the GIT version of GPGME please see the file README.GIT for more information. diff --git a/configure.ac b/configure.ac index 1111849..f3d3195 100644 --- a/configure.ac +++ b/configure.ac @@ -55,10 +55,10 @@ AC_INIT([gpgme],[mym4_full_version],[http://bugs.gnupg.org]) # (Interfaces added: AGE++) # (Interfaces removed/changed: AGE=0) # -LIBGPGME_LT_CURRENT=22 +LIBGPGME_LT_CURRENT=23 # Subtract 2 from this value if you want to make the LFS transition an # ABI break. [Note to self: Remove this comment with the next regular break.] -LIBGPGME_LT_AGE=11 +LIBGPGME_LT_AGE=12 LIBGPGME_LT_REVISION=0 # If the API is changed in an incompatible way: increment the next counter. ----------------------------------------------------------------------- Summary of changes: NEWS | 34 ++++++++++++++++++++-------------- README | 10 +++------- configure.ac | 4 ++-- 3 files changed, 25 insertions(+), 23 deletions(-) hooks/post-receive -- GnuPG Made Easy http://git.gnupg.org From cvs at cvs.gnupg.org Wed May 21 09:42:04 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 21 May 2014 09:42:04 +0200 Subject: [git] GPGME - branch, master, updated. gpgme-1.5.0-1-gee0f177 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 ee0f17736ec18074700ae83cdf6821e5f8c19c7c (commit) from 0eca21113c1d1ab2aea58e1ea21075f472f99c23 (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 ee0f17736ec18074700ae83cdf6821e5f8c19c7c Author: Werner Koch Date: Wed May 21 09:43:53 2014 +0200 Post release updates -- diff --git a/NEWS b/NEWS index 82d4914..b7a6227 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +Noteworthy changes in version 1.5.1 (unreleased) [C__/A__/R_] +------------------------------------------------------------- + + Noteworthy changes in version 1.5.0 (2014-05-21) [C23/A12/R0] ------------------------------------------------------------- diff --git a/configure.ac b/configure.ac index f3d3195..92c9463 100644 --- a/configure.ac +++ b/configure.ac @@ -29,7 +29,7 @@ min_automake_version="1.11" # for the LT versions. m4_define(mym4_version_major, [1]) m4_define(mym4_version_minor, [5]) -m4_define(mym4_version_micro, [0]) +m4_define(mym4_version_micro, [1]) # Below is m4 magic to extract and compute the revision number, the # decimalized short revision number, a beta version string, and a flag ----------------------------------------------------------------------- Summary of changes: NEWS | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) hooks/post-receive -- GnuPG Made Easy http://git.gnupg.org From cvs at cvs.gnupg.org Mon May 26 17:04:34 2014 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Mon, 26 May 2014 17:04:34 +0200 Subject: [git] gnupg-doc - branch, master, updated. 777feabd40d78631a11a0998e06597037e9e77a0 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 GnuPG website and other docs". The branch, master has been updated via 777feabd40d78631a11a0998e06597037e9e77a0 (commit) via 387e2b10ef4024712ac2816bfe5f097693547d0d (commit) from d5981896f2e8068837d2a6b40769880e8ec4607a (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 777feabd40d78631a11a0998e06597037e9e77a0 Author: Werner Koch Date: Mon May 26 17:05:59 2014 +0200 web: Add new donation system -- We now use Stripe.com for credit card processing. This required quite some work on our site for proper and not too privicy intrusive payments. To make the system work the Payproc at git://git.gnupg.org/payproc.git needs to be installed. diff --git a/cgi/config.rc b/cgi/config.rc new file mode 100644 index 0000000..64290f2 --- /dev/null +++ b/cgi/config.rc @@ -0,0 +1,7 @@ +# config.rc - Configuration variables for all CGIs -*- perl -*- + +htdocs => '/var/www/www/www.gnupg.org/htdocs/', + +payprocd_socket => '/var/run/payproc/daemon', + +#eof# diff --git a/cgi/procdonate.cgi b/cgi/procdonate.cgi new file mode 100755 index 0000000..664ba8c --- /dev/null +++ b/cgi/procdonate.cgi @@ -0,0 +1,487 @@ +#!/usr/bin/perl -T + +# procdonate.cgi - Donation payment processor for gnupg.org +# Copyright (C) 2014 g10 Code GmbH +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + +use strict; +use CGI; +use Cwd qw(realpath); +use IO::Socket::UNIX; + +realpath($0) =~ /^(.*)\/.*$/; +my %config = do $1 . '/config.rc'; + +my $htdocs = $config{htdocs}; +my $socket_name = $config{payprocd_socket}; +my $error_marker = '* error'; + +# The form variabales are accessed via Q. +my $q = new CGI; + +# This is a multi-purpose CGI. The mode decides what to do. +my $mode = $q->param("mode"); +my $sessid = $q->param("sessid"); + +# Variables used in the template pages. +my $amount = ""; +my $stripeamount = ""; +my $currency = ""; +my $name = ""; +my $mail = ""; +my $message = ""; +my $errorstr = ""; + +# We use a dictionary to track error. Those errors will then be +# inserted into the output by write_template. +my %errdict = (); + +# Prototypes +sub fail ($); + + +# Write a template file. A template is a proper HTML file with +# variables enclosed in HTML comments. To allow inserting data into +# a value attribute of an input field, such a tag needs to be written as +# +# the result after processing will be +# +# assuming that the value of FOO is foo. Note that this substitution +# rules work for all tags and thus you better take care to add an +# extra space if if do not want this to happen. +sub write_template ($) { + my $fname = shift; + + my $errorpanel = ''; + my $err_amount = ''; + my $err_name = ''; + my $err_mail = ''; + my $checkother = ' checked="checked"'; + my $sel_eur = ''; + my $sel_usd = ''; + my $sel_gbp = ''; + my $sel_jpy = ''; + my $message_fmt; + + # Avoid broken HTML attributes. + $amount =~ s/\x22/\x27/g; + $stripeamount =~ s/\x22/\x27/g; + $currency =~ s/\x22/\x27/g; + $name =~ s/\x22/\x27/g; + $mail =~ s/\x22/\x27/g; + $message =~ s/\x22/\x27/g; + + # Clean possible user provided data + $sessid =~ s//g; + print STDERR "selected currecny->$currency<-\n"; + if ( $currency =~ /EUR/i ) { + $sel_eur = ' selected="selected"'; + } elsif ( $currency =~ /USD/i ) { + $sel_usd = ' selected="selected"'; + } elsif ( $currency =~ /GBP/i ) { + $sel_gbp = ' selected="selected"'; + } elsif ( $currency =~ /JPY/i ) { + $sel_jpy = ' selected="selected"'; + } + print STDERR "selected currecny->$sel_gbp<-\n"; + + # Build error strings. + foreach (keys %errdict) + { + if (/amount/) { $err_amount = $error_marker; } + elsif (/name/) { $err_name = $error_marker; } + elsif (/mail/) { $err_mail = $error_marker; } + + $errorpanel = $errorpanel . "Field $_: " . $errdict{$_} . "
\n" + } + if ( $errorpanel ne '' ) + { + $errorpanel = + "

\n" . $errorpanel . "

\n"; + } + + open TEMPLATE, $htdocs . $fname; + while (