by Werner Koch | 25 Jul 08:21 2014
Picon

[git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-98-g4556f9b

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  4556f9b19c024f16bdf542da7173395c0741b91d (commit)
       via  0e10902ad7584277ac966367efc712b183784532 (commit)
       via  4e0bf1b9190ce08fb23eb3ae0c3be58954ff36ab (commit)
      from  4846e52728970e3117f3a046ef9010be089a3ae4 (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 4556f9b19c024f16bdf542da7173395c0741b91d
Author: Werner Koch <wk <at> gnupg.org>
Date:   Thu Jul 24 12:30:32 2014 +0200

    ecc: Support the non-standard 0x40 compression flag for EdDSA.

    * cipher/ecc.c (ecc_generate): Check the "comp" flag for EdDSA.
    * cipher/ecc-eddsa.c (eddsa_encode_x_y): Add arg WITH_PREFIX.
    (_gcry_ecc_eddsa_encodepoint): Ditto.
    (_gcry_ecc_eddsa_ensure_compact): Handle the 0x40 compression prefix.
    (_gcry_ecc_eddsa_decodepoint): Ditto.
    * tests/keygrip.c: Check an compresssed with prefix Ed25519 key.
    * tests/t-ed25519.inp: Ditto.

diff --git a/cipher/ecc-common.h b/cipher/ecc-common.h
(Continue reading)

Markus Teich | 21 Jul 22:50 2014
Picon

[PATCH] typo

---
 mpi/ec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mpi/ec.c b/mpi/ec.c
index 4f35de0..2dd1397 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
 <at>  <at>  -999,7 +999,7  <at>  <at>  add_points_edwards (mpi_point_t result,
 #define G (ctx->t.scratch[6])
 #define tmp (ctx->t.scratch[7])

-  /* Compute: (X_3 : Y_3 : Z_3) = (X_1 : Y_1 : Z_1) + (X_2 : Y_2 : Z_3)  */
+  /* Compute: (X_3 : Y_3 : Z_3) = (X_1 : Y_1 : Z_1) + (X_2 : Y_2 : Z_2)  */

   /* A = Z1 ยท Z2 */
   ec_mulm (A, Z1, Z2, ctx);
--

-- 
1.8.5.5

_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel <at> gnupg.org
http://lists.gnupg.org/mailman/listinfo/gcrypt-devel
by NIIBE Yutaka | 16 Jul 10:14 2014
Picon

[git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-95-g4846e52

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  4846e52728970e3117f3a046ef9010be089a3ae4 (commit)
      from  1b9b00bbe41bbed32563f1102049521e703e72bd (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 4846e52728970e3117f3a046ef9010be089a3ae4
Author: NIIBE Yutaka <gniibe <at> fsij.org>
Date:   Wed Jul 16 17:05:55 2014 +0900

    mpi: Add mpi_swap_cond.

    * mpi/mpiutil.c (_gcry_mpi_swap_cond): New.
    * src/mpi.h (mpi_swap_cond): New.
    --

    This is an internal function for now.

diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c
index fdce578..f74dd91 100644
--- a/mpi/mpiutil.c
+++ b/mpi/mpiutil.c
 <at>  <at>  -542,6 +542,34  <at>  <at>  _gcry_mpi_swap (gcry_mpi_t a, gcry_mpi_t b)
(Continue reading)

Christian Grothoff | 10 Jul 19:35 2014
Picon

Re: ec subtract

Hohey!

Sounds like a question for libgcrypt hackers.  Extending the API to
make it trivial to invert a point would make sense IMO.

Happy hacking!

Christian

On 07/10/2014 07:14 PM, Markus Teich wrote:
> Heyho,
>
> for the ECBD I need to subtract two points on the curve (Z_{i+1} - Z_{i-1}). I
> found out[0], that I have to invert the y value of the second point to achieve
> this. However in libgcrypt (1.6.1) there seems to be no function, which achieves
> that easily[1]. Do I really have to use gcry_mpi_point_get, gcry_mpi_sub and
> gcry_mpi_point_set to invert the point?
>
> A gcry_mpi_ec_sub should definitely be supplied by the libgcrypt API.
>
> --Markus
>
>
> [0] http://crypto.stackexchange.com/questions/11316/subtracting-a-point-in-elliptic-curve-cryptography
> [1] https://www.gnupg.org/documentation/manuals/gcrypt/EC-functions.html

Attachment (0x48426C7E.asc): application/pgp-keys, 25 KiB
_______________________________________________
(Continue reading)

Erik Nyquist | 8 Jul 12:35 2014
Picon

AES-NI support detection: possible bug?

I tried compiling libgcrypt-1.5.0 on a platform with a Quark SoC (intel low- power SoC, which does not support AES instructions):

root <at> clanton:/media/mmcblk0p1# cat /proc/cpuinfo
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 5
model           : 9
model name      : 05/09
stepping        : 0
cpu MHz         : 399.076
cache size      : 0 KB
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : yes
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 7
wp              : yes
flags           : fpu vme pse tsc msr pae cx8 apic pbe nx smep
bogomips        : 798.15
clflush size    : 32
cache_alignment : 32
address sizes   : 32 bits physical, 32 bits virtual
power management:

During configure, the feature detection for AES-NI appears to return with the result that yes, AES instructions are supported (incorrectly so):

 Try using AES-NI crypto:   yes


So at run time, I get an 'illegal instruction' error. This was initially noticed while trying to connect to a wifi access point using wpa_supplicant- it can also be seen when running the tests included with libgcrypt:

root <at> clanton:/media/mmcblk0p1/libgcrypt-1.5.0-beta1# make check

ciphers:arcfour:blowfish:cast5:des:aes:twofish:serpent:rfc2268:seed:camellia:
pubkeys:dsa:elgamal:rsa:ecc:
digests:crc:md4:md5:rmd160:sha1:sha256:sha512:tiger:whirlpool:
rnd-mod:linux:
mpi-asm:i586/mpih-add1.S:i586/mpih-sub1.S:i586/mpih-mul1.S:i586/mpih-mul2.S:i586/mpih-mul3.S:i586/mpih-lshift.S:i586/mpih-rshift.S:
hwflist:
fips-mode:n:n:
PASS: version
PASS: t-mpi-bit
PASS: prime
PASS: register
PASS: ac
PASS: ac-schemes
PASS: ac-data
/bin/sh: line 4:  7998 Illegal instruction     ${dir}$tst
FAIL: basic
PASS: mpitests
PASS: tsexp
PASS: keygen
PASS: pubkey
PASS: hmac
PASS: keygrip
PASS: fips186-dsa
PASS: aeswrap
PASS: curves
PASS: random
MD5             50ms   120ms   750ms    90ms    50ms
SHA1           130ms   190ms   830ms   170ms   130ms
RIPEMD160      140ms   200ms   850ms   190ms   140ms
TIGER192       250ms   360ms  1150ms   320ms   250ms
SHA256         290ms   430ms  1140ms   330ms   290ms
SHA384         500ms   720ms  1330ms   540ms   480ms
SHA512         490ms   730ms  1320ms   540ms   480ms
SHA224         290ms   440ms  1130ms   330ms   290ms
MD4             40ms   100ms   750ms    80ms    40ms
CRC32           30ms    40ms   570ms    80ms    40ms
CRC32RFC1510    30ms    30ms   570ms    80ms    40ms
CRC24RFC2440   260ms   260ms   770ms   300ms   270ms
WHIRLPOOL     1740ms  1950ms  2530ms  1820ms  1740ms
TIGER          260ms   350ms  1150ms   320ms   250ms
TIGER2         260ms   350ms  1150ms   320ms   250ms

                ECB/Stream         CBC             CFB             OFB             CTR
             --------------- --------------- --------------- --------------- ---------------
3DES          1160ms  1160ms  1220ms  1260ms  1200ms  1220ms  1220ms  1210ms  1310ms  1330ms
CAST5          400ms   410ms   460ms   470ms   440ms   460ms   460ms   460ms   550ms   530ms
BLOWFISH       380ms   410ms   430ms   490ms   410ms   430ms   430ms   430ms   530ms   520ms
AES            340ms   350ms/bin/sh: line 4:  8244 Illegal instruction     ${dir}$tst
FAIL: benchmark
========================================
2 of 19 tests failed
========================================
make[2]: *** [check-TESTS] Error 1
make[2]: Leaving directory `/media/mmcblk0p1/libgcrypt-1.5.0-beta1/tests'
make[1]: *** [check-am] Error 2
make[1]: Leaving directory `/media/mmcblk0p1/libgcrypt-1.5.0-beta1/tests'
make: *** [check-recursive] Error 1


Has anyone seen any similar issues with configure failing to detect AES support accurately?

Erik.

_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel <at> gnupg.org
http://lists.gnupg.org/mailman/listinfo/gcrypt-devel
Colin Davis | 8 Jul 07:45 2014

Make fig2dev optional?

Installing fig2dev is unfortunately rather difficult on OSX, since it has a lot of prerequisites, and is
not bundled with homebrew.
Unfortunately, I didn't see an easy way to bypass creating these figures, other than manually editing the
Makefile every time..

I added a check, which will look to see if fig2dev is installed. If not, it doesn't add the images to BUILT_SOURCES
There may be a cleaner way to do this, but this lets me build lib

There may well be a cleaner way to do this, but lets me build without fig2dev, while still running it if
fig2dev is installed.

-CPD

https://gist.githubusercontent.com/e1ven/01244536540ae08c7dc1/raw/14b91133ddf0f616856afbab49d3251291606b5f/fig2dev.patch
From a038af5b9d747161f79ef0f28dfb848aa50fe81f Mon Sep 17 00:00:00 2001
From: Colin Davis <e1ven <at> e1ven.com>
Date: Tue, 8 Jul 2014 01:23:29 -0400
Subject: [PATCH] Make fig2dev optional

---
 configure.ac    |  2 ++
 doc/Makefile.am | 18 ++++++++++--------
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/configure.ac b/configure.ac
index c5952c7..58c276f 100644
--- a/configure.ac
+++ b/configure.ac
 <at>  <at>  -1334,6 +1334,8  <at>  <at>  if test "$gcry_cv_cc_arm_arch_is_v6" = "yes" ; then
      [Defined if ARM architecture is v6 or newer])
 fi

+AC_CHECK_PROG([fig2dev], fig2dev, yes, no)
+AM_CONDITIONAL([FOUND_FIG2DEV], [test "x$fig2dev" = xyes])

 #
 # Check whether GCC inline assembler supports NEON instructions
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 30330bb..782ec6a 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
 <at>  <at>  -17,18 +17,20  <at>  <at> 
 # License along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA

-EXTRA_DIST = README.apichanges HACKING DCO \
-	     libgcrypt-modules.eps fips-fsm.eps \
-	     libgcrypt-modules.png fips-fsm.png \
-             libgcrypt-modules.pdf fips-fsm.pdf \
-	     yat2m.c
-
-DISTCLEANFILES = gcrypt.cps yat2m-stamp.tmp yat2m-stamp $(myman_pages)
-CLEANFILES = yat2m

+if FOUND_FIG2DEV
 BUILT_SOURCES = libgcrypt-modules.eps fips-fsm.eps \
                 libgcrypt-modules.png fips-fsm.png \
                 libgcrypt-modules.pdf fips-fsm.pdf
+else
+	BUILT_SOURCES = ""
+endif
+
+EXTRA_DIST = README.apichanges HACKING DCO \
+	     yat2m.c $(BUILT_SOURCES)
+
+DISTCLEANFILES = gcrypt.cps yat2m-stamp.tmp yat2m-stamp $(myman_pages)
+CLEANFILES = yat2m

 info_TEXINFOS = gcrypt.texi
 gcrypt_TEXINFOS = lgpl.texi gpl.texi libgcrypt-modules.fig fips-fsm.fig
--

-- 
2.0.1
Dmitry Eremin-Solenikov | 30 Jun 02:04 2014
Picon

[PATCH 1/3] Stribog: change endianness of the final result

* cipher/stribog.c: change endianness of the hash result.
* tests/basic.c (check_digests): adapt Stribog tests.
--
Stribog standard (GOST R 34.11-2012) is a bit vague on the
representation of the final result. This mistake is supported by GOST
signatures being not so clear on the endianness of the hash value.
Fix the Stribog result endianness to fully confirm to standard.
This is proven by a (draft) publication of PBKDF2 test cases done by
TC26.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>
---
 cipher/stribog.c | 165 +++++++++++++++++++++++++------------------------------
 tests/basic.c    |  24 ++++----
 2 files changed, 86 insertions(+), 103 deletions(-)

diff --git a/cipher/stribog.c b/cipher/stribog.c
index 942bbf4..360cfec 100644
--- a/cipher/stribog.c
+++ b/cipher/stribog.c
 <at>  <at>  -1080,70 +1080,70  <at>  <at>  static const u64 stribog_table[8][256] =
     U64_C(0x72d14d3493b2e388), U64_C(0xd6a30f258c153427) },
 };

-static const u64 C16[13][16] =
+static const u64 C16[12][8] =
 {
-  { U64_C(0xdd806559f2a64507), U64_C(0x05767436cc744d23),
-    U64_C(0xa2422a08a460d315), U64_C(0x4b7ce09192676901),
-    U64_C(0x714eb88d7585c4fc), U64_C(0x2f6a76432e45d016),
-    U64_C(0xebcb2f81c0657c1f), U64_C(0xb1085bda1ecadae9) },
-  { U64_C(0xe679047021b19bb7), U64_C(0x55dda21bd7cbcd56),
-    U64_C(0x5cb561c2db0aa7ca), U64_C(0x9ab5176b12d69958),
-    U64_C(0x61d55e0f16b50131), U64_C(0xf3feea720a232b98),
-    U64_C(0x4fe39d460f70b5d7), U64_C(0x6fa3b58aa99d2f1a) },
-  { U64_C(0x991e96f50aba0ab2), U64_C(0xc2b6f443867adb31),
-    U64_C(0xc1c93a376062db09), U64_C(0xd3e20fe490359eb1),
-    U64_C(0xf2ea7514b1297b7b), U64_C(0x06f15e5f529c1f8b),
-    U64_C(0x0a39fc286a3d8435), U64_C(0xf574dcac2bce2fc7) },
-  { U64_C(0x220cbebc84e3d12e), U64_C(0x3453eaa193e837f1),
-    U64_C(0xd8b71333935203be), U64_C(0xa9d72c82ed03d675),
-    U64_C(0x9d721cad685e353f), U64_C(0x488e857e335c3c7d),
-    U64_C(0xf948e1a05d71e4dd), U64_C(0xef1fdfb3e81566d2) },
-  { U64_C(0x601758fd7c6cfe57), U64_C(0x7a56a27ea9ea63f5),
-    U64_C(0xdfff00b723271a16), U64_C(0xbfcd1747253af5a3),
-    U64_C(0x359e35d7800fffbd), U64_C(0x7f151c1f1686104a),
-    U64_C(0x9a3f410c6ca92363), U64_C(0x4bea6bacad474799) },
-  { U64_C(0xfa68407a46647d6e), U64_C(0xbf71c57236904f35),
-    U64_C(0x0af21f66c2bec6b6), U64_C(0xcffaa6b71c9ab7b4),
-    U64_C(0x187f9ab49af08ec6), U64_C(0x2d66c4f95142a46c),
-    U64_C(0x6fa4c33b7a3039c0), U64_C(0xae4faeae1d3ad3d9) },
-  { U64_C(0x8886564d3a14d493), U64_C(0x3517454ca23c4af3),
-    U64_C(0x06476983284a0504), U64_C(0x0992abc52d822c37),
-    U64_C(0xd3473e33197a93c9), U64_C(0x399ec6c7e6bf87c9),
-    U64_C(0x51ac86febf240954), U64_C(0xf4c70e16eeaac5ec) },
-  { U64_C(0xa47f0dd4bf02e71e), U64_C(0x36acc2355951a8d9),
-    U64_C(0x69d18d2bd1a5c42f), U64_C(0xf4892bcb929b0690),
-    U64_C(0x89b4443b4ddbc49a), U64_C(0x4eb7f8719c36de1e),
-    U64_C(0x03e7aa020c6e4141), U64_C(0x9b1f5b424d93c9a7) },
-  { U64_C(0x7261445183235adb), U64_C(0x0e38dc92cb1f2a60),
-    U64_C(0x7b2b8a9aa6079c54), U64_C(0x800a440bdbb2ceb1),
-    U64_C(0x3cd955b7e00d0984), U64_C(0x3a7d3a1b25894224),
-    U64_C(0x944c9ad8ec165fde), U64_C(0x378f5a541631229b) },
-  { U64_C(0x74b4c7fb98459ced), U64_C(0x3698fad1153bb6c3),
-    U64_C(0x7a1e6c303b7652f4), U64_C(0x9fe76702af69334b),
-    U64_C(0x1fffe18a1b336103), U64_C(0x8941e71cff8a78db),
-    U64_C(0x382ae548b2e4f3f3), U64_C(0xabbedea680056f52) },
-  { U64_C(0x6bcaa4cd81f32d1b), U64_C(0xdea2594ac06fd85d),
-    U64_C(0xefbacd1d7d476e98), U64_C(0x8a1d71efea48b9ca),
-    U64_C(0x2001802114846679), U64_C(0xd8fa6bbbebab0761),
-    U64_C(0x3002c6cd635afe94), U64_C(0x7bcd9ed0efc889fb) },
-  { U64_C(0x48bc924af11bd720), U64_C(0xfaf417d5d9b21b99),
-    U64_C(0xe71da4aa88e12852), U64_C(0x5d80ef9d1891cc86),
-    U64_C(0xf82012d430219f9b), U64_C(0xcda43c32bcdf1d77),
-    U64_C(0xd21380b00449b17a), U64_C(0x378ee767f11631ba) },
+  { U64_C(0xb1085bda1ecadae9), U64_C(0xebcb2f81c0657c1f),
+    U64_C(0x2f6a76432e45d016), U64_C(0x714eb88d7585c4fc),
+    U64_C(0x4b7ce09192676901), U64_C(0xa2422a08a460d315),
+    U64_C(0x05767436cc744d23), U64_C(0xdd806559f2a64507) },
+  { U64_C(0x6fa3b58aa99d2f1a), U64_C(0x4fe39d460f70b5d7),
+    U64_C(0xf3feea720a232b98), U64_C(0x61d55e0f16b50131),
+    U64_C(0x9ab5176b12d69958), U64_C(0x5cb561c2db0aa7ca),
+    U64_C(0x55dda21bd7cbcd56), U64_C(0xe679047021b19bb7) },
+  { U64_C(0xf574dcac2bce2fc7), U64_C(0x0a39fc286a3d8435),
+    U64_C(0x06f15e5f529c1f8b), U64_C(0xf2ea7514b1297b7b),
+    U64_C(0xd3e20fe490359eb1), U64_C(0xc1c93a376062db09),
+    U64_C(0xc2b6f443867adb31), U64_C(0x991e96f50aba0ab2) },
+  { U64_C(0xef1fdfb3e81566d2), U64_C(0xf948e1a05d71e4dd),
+    U64_C(0x488e857e335c3c7d), U64_C(0x9d721cad685e353f),
+    U64_C(0xa9d72c82ed03d675), U64_C(0xd8b71333935203be),
+    U64_C(0x3453eaa193e837f1), U64_C(0x220cbebc84e3d12e) },
+  { U64_C(0x4bea6bacad474799), U64_C(0x9a3f410c6ca92363),
+    U64_C(0x7f151c1f1686104a), U64_C(0x359e35d7800fffbd),
+    U64_C(0xbfcd1747253af5a3), U64_C(0xdfff00b723271a16),
+    U64_C(0x7a56a27ea9ea63f5), U64_C(0x601758fd7c6cfe57) },
+  { U64_C(0xae4faeae1d3ad3d9), U64_C(0x6fa4c33b7a3039c0),
+    U64_C(0x2d66c4f95142a46c), U64_C(0x187f9ab49af08ec6),
+    U64_C(0xcffaa6b71c9ab7b4), U64_C(0x0af21f66c2bec6b6),
+    U64_C(0xbf71c57236904f35), U64_C(0xfa68407a46647d6e) },
+  { U64_C(0xf4c70e16eeaac5ec), U64_C(0x51ac86febf240954),
+    U64_C(0x399ec6c7e6bf87c9), U64_C(0xd3473e33197a93c9),
+    U64_C(0x0992abc52d822c37), U64_C(0x06476983284a0504),
+    U64_C(0x3517454ca23c4af3), U64_C(0x8886564d3a14d493) },
+  { U64_C(0x9b1f5b424d93c9a7), U64_C(0x03e7aa020c6e4141),
+    U64_C(0x4eb7f8719c36de1e), U64_C(0x89b4443b4ddbc49a),
+    U64_C(0xf4892bcb929b0690), U64_C(0x69d18d2bd1a5c42f),
+    U64_C(0x36acc2355951a8d9), U64_C(0xa47f0dd4bf02e71e) },
+  { U64_C(0x378f5a541631229b), U64_C(0x944c9ad8ec165fde),
+    U64_C(0x3a7d3a1b25894224), U64_C(0x3cd955b7e00d0984),
+    U64_C(0x800a440bdbb2ceb1), U64_C(0x7b2b8a9aa6079c54),
+    U64_C(0x0e38dc92cb1f2a60), U64_C(0x7261445183235adb) },
+  { U64_C(0xabbedea680056f52), U64_C(0x382ae548b2e4f3f3),
+    U64_C(0x8941e71cff8a78db), U64_C(0x1fffe18a1b336103),
+    U64_C(0x9fe76702af69334b), U64_C(0x7a1e6c303b7652f4),
+    U64_C(0x3698fad1153bb6c3), U64_C(0x74b4c7fb98459ced) },
+  { U64_C(0x7bcd9ed0efc889fb), U64_C(0x3002c6cd635afe94),
+    U64_C(0xd8fa6bbbebab0761), U64_C(0x2001802114846679),
+    U64_C(0x8a1d71efea48b9ca), U64_C(0xefbacd1d7d476e98),
+    U64_C(0xdea2594ac06fd85d), U64_C(0x6bcaa4cd81f32d1b) },
+  { U64_C(0x378ee767f11631ba), U64_C(0xd21380b00449b17a),
+    U64_C(0xcda43c32bcdf1d77), U64_C(0xf82012d430219f9b),
+    U64_C(0x5d80ef9d1891cc86), U64_C(0xe71da4aa88e12852),
+    U64_C(0xfaf417d5d9b21b99), U64_C(0x48bc924af11bd720) },
 };

 
 #define strido(out, temp, i) do { \
 	u64 t; \
-	t  = stribog_table[0][(temp[0] >> (i * 8)) & 0xff]; \
-	t ^= stribog_table[1][(temp[1] >> (i * 8)) & 0xff]; \
-	t ^= stribog_table[2][(temp[2] >> (i * 8)) & 0xff]; \
-	t ^= stribog_table[3][(temp[3] >> (i * 8)) & 0xff]; \
-	t ^= stribog_table[4][(temp[4] >> (i * 8)) & 0xff]; \
-	t ^= stribog_table[5][(temp[5] >> (i * 8)) & 0xff]; \
-	t ^= stribog_table[6][(temp[6] >> (i * 8)) & 0xff]; \
-	t ^= stribog_table[7][(temp[7] >> (i * 8)) & 0xff]; \
-	out[i] = t; } while(0)
+	t  = stribog_table[0][(temp[7] >> (i * 8)) & 0xff]; \
+	t ^= stribog_table[1][(temp[6] >> (i * 8)) & 0xff]; \
+	t ^= stribog_table[2][(temp[5] >> (i * 8)) & 0xff]; \
+	t ^= stribog_table[3][(temp[4] >> (i * 8)) & 0xff]; \
+	t ^= stribog_table[4][(temp[3] >> (i * 8)) & 0xff]; \
+	t ^= stribog_table[5][(temp[2] >> (i * 8)) & 0xff]; \
+	t ^= stribog_table[6][(temp[1] >> (i * 8)) & 0xff]; \
+	t ^= stribog_table[7][(temp[0] >> (i * 8)) & 0xff]; \
+	out[7-i] = t; } while(0)

 static void LPSX (u64 *out, const u64 *a, const u64 *b)
 {
 <at>  <at>  -1227,14 +1227,14  <at>  <at>  transform_bits (STRIBOG_CONTEXT *hd, const unsigned char *data, unsigned count)
   int i;

   for (i = 0; i < 8; i++)
-    M[i] = buf_get_le64(data + i * 8);
+    M[7-i] = buf_get_le64(data + i * 8);

   g (hd->h, M, hd->N);
-  l = hd->N[0];
-  hd->N[0] += count;
-  if (hd->N[0] < l)
+  l = hd->N[7];
+  hd->N[7] += count;
+  if (hd->N[7] < l)
     { /* overflow */
-      for (i = 1; i < 8; i++)
+      for (i = 6; i >= 0; i++)
         {
           hd->N[i]++;
           if (hd->N[i] != 0)
 <at>  <at>  -1242,22 +1242,12  <at>  <at>  transform_bits (STRIBOG_CONTEXT *hd, const unsigned char *data, unsigned count)
         }
     }

-  hd->Sigma[0] += M[0];
-  for (i = 1; i < 8; i++)
-    if (hd->Sigma[i-1] < M[i-1])
-      hd->Sigma[i] += M[i] + 1;
+  hd->Sigma[7] += M[7];
+  for (i = 7; i >= 1; i--)
+    if (hd->Sigma[i] < M[i])
+      hd->Sigma[i-1] += M[i-1] + 1;
     else
-      hd->Sigma[i] += M[i];
-}
-
-static unsigned int
-transform_blk (void *context, const unsigned char *inbuf_arg)
-{
-  STRIBOG_CONTEXT *hd = context;
-
-  transform_bits (hd, inbuf_arg, 64 * 8);
-
-  return /* burn_stack */ 768;
+      hd->Sigma[i-1] += M[i-1];
 }

 static unsigned int
 <at>  <at>  -1267,7 +1257,8  <at>  <at>  transform ( void *c, const unsigned char *data, size_t nblks )

   do
     {
-      burn = transform_blk (c, data);
+      transform_bits (c, data, 64 * 8);
+      burn = /* burn_stack */ 768;
       data += 64;
     }
   while (--nblks);
 <at>  <at>  -1300,32 +1291,24  <at>  <at>  stribog_final (void *context)
   g (hd->h, hd->Sigma, Z);

   for (i = 0; i < 8; i++)
-    hd->h[i] = le_bswap64(hd->h[i]);
+    hd->h[i] = be_bswap64(hd->h[i]);

   _gcry_burn_stack (768);
 }

 static byte *
-stribog_read_512 (void *context)
+stribog_read (void *context)
 {
   STRIBOG_CONTEXT *hd = context;

   return hd->result;
 }

-static byte *
-stribog_read_256 (void *context)
-{
-  STRIBOG_CONTEXT *hd = context;
-
-  return hd->result + 32;
-}
-
 gcry_md_spec_t _gcry_digest_spec_stribog_256 =
   {
     GCRY_MD_STRIBOG256, {0, 0},
     "STRIBOG256", NULL, 0, NULL, 32,
-    stribog_init_256, _gcry_md_block_write, stribog_final, stribog_read_256,
+    stribog_init_256, _gcry_md_block_write, stribog_final, stribog_read,
     sizeof (STRIBOG_CONTEXT)
   };

 <at>  <at>  -1333,6 +1316,6  <at>  <at>  gcry_md_spec_t _gcry_digest_spec_stribog_512 =
   {
     GCRY_MD_STRIBOG512, {0, 0},
     "STRIBOG512", NULL, 0, NULL, 64,
-    stribog_init_512, _gcry_md_block_write, stribog_final, stribog_read_512,
+    stribog_init_512, _gcry_md_block_write, stribog_final, stribog_read,
     sizeof (STRIBOG_CONTEXT)
   };
diff --git a/tests/basic.c b/tests/basic.c
index 6d70cfd..f312fc0 100644
--- a/tests/basic.c
+++ b/tests/basic.c
 <at>  <at>  -4870,32 +4870,32  <at>  <at>  check_digests (void)
 	"\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"
-        "\xb1\x9a\xbc\x24\x75\x22\x2f\x35\xc0\x85\x12\x2b\xe4\xba\x1f\xfa"
-        "\x00\xad\x30\xf8\x76\x7b\x3a\x82\x38\x4c\x65\x74\xf0\x24\xc3\x11"
-        "\xe2\xa4\x81\x33\x2b\x08\xef\x7f\x41\x79\x78\x91\xc1\x64\x6f\x48" },
+        "\x48\x6f\x64\xc1\x91\x78\x79\x41\x7f\xef\x08\x2b\x33\x81\xa4\xe2"
+        "\x11\xc3\x24\xf0\x74\x65\x4c\x38\x82\x3a\x7b\x76\xf8\x30\xad\x00"
+        "\xfa\x1f\xba\xe4\x2b\x12\x85\xc0\x35\x2f\x22\x75\x24\xbc\x9a\xb1"
+        "\x62\x54\x28\x8d\xd6\x86\x3d\xcc\xd5\xb9\xf5\x4a\x1a\xd0\x54\x1b" },
       { GCRY_MD_STRIBOG256,
         "012345678901234567890123456789012345678901234567890123456789012",
-        "\x9d\x15\x1e\xef\xd8\x59\x0b\x89\xda\xa6\xba\x6c\xb7\x4a\xf9\x27"
-        "\x5d\xd0\x51\x02\x6b\xb1\x49\xa4\x52\xfd\x84\xe5\xe5\x7b\x55\x00" },
+        "\x00\x55\x7b\xe5\xe5\x84\xfd\x52\xa4\x49\xb1\x6b\x02\x51\xd0\x5d"
+        "\x27\xf9\x4a\xb7\x6c\xba\xa6\xda\x89\x0b\x59\xd8\xef\x1e\x15\x9d" },
       { GCRY_MD_STRIBOG512,
         "\xd1\xe5\x20\xe2\xe5\xf2\xf0\xe8\x2c\x20\xd1\xf2\xf0\xe8\xe1\xee"
         "\xe6\xe8\x20\xe2\xed\xf3\xf6\xe8\x2c\x20\xe2\xe5\xfe\xf2\xfa\x20"
         "\xf1\x20\xec\xee\xf0\xff\x20\xf1\xf2\xf0\xe5\xeb\xe0\xec\xe8\x20"
         "\xed\xe0\x20\xf5\xf0\xe0\xe1\xf0\xfb\xff\x20\xef\xeb\xfa\xea\xfb"
         "\x20\xc8\xe3\xee\xf0\xe5\xe2\xfb",
-        "\x1e\x88\xe6\x22\x26\xbf\xca\x6f\x99\x94\xf1\xf2\xd5\x15\x69\xe0"
-        "\xda\xf8\x47\x5a\x3b\x0f\xe6\x1a\x53\x00\xee\xe4\x6d\x96\x13\x76"
-        "\x03\x5f\xe8\x35\x49\xad\xa2\xb8\x62\x0f\xcd\x7c\x49\x6c\xe5\xb3"
-        "\x3f\x0c\xb9\xdd\xdc\x2b\x64\x60\x14\x3b\x03\xda\xba\xc9\xfb\x28" },
+        "\x28\xfb\xc9\xba\xda\x03\x3b\x14\x60\x64\x2b\xdc\xdd\xb9\x0c\x3f"
+        "\xb3\xe5\x6c\x49\x7c\xcd\x0f\x62\xb8\xa2\xad\x49\x35\xe8\x5f\x03"
+        "\x76\x13\x96\x6d\xe4\xee\x00\x53\x1a\xe6\x0f\x3b\x5a\x47\xf8\xda"
+        "\xe0\x69\x15\xd5\xf2\xf1\x94\x99\x6f\xca\xbf\x26\x22\xe6\x88\x1e" },
       { GCRY_MD_STRIBOG256,
         "\xd1\xe5\x20\xe2\xe5\xf2\xf0\xe8\x2c\x20\xd1\xf2\xf0\xe8\xe1\xee"
         "\xe6\xe8\x20\xe2\xed\xf3\xf6\xe8\x2c\x20\xe2\xe5\xfe\xf2\xfa\x20"
         "\xf1\x20\xec\xee\xf0\xff\x20\xf1\xf2\xf0\xe5\xeb\xe0\xec\xe8\x20"
         "\xed\xe0\x20\xf5\xf0\xe0\xe1\xf0\xfb\xff\x20\xef\xeb\xfa\xea\xfb"
         "\x20\xc8\xe3\xee\xf0\xe5\xe2\xfb",
-        "\x9d\xd2\xfe\x4e\x90\x40\x9e\x5d\xa8\x7f\x53\x97\x6d\x74\x05\xb0"
-        "\xc0\xca\xc6\x28\xfc\x66\x9a\x74\x1d\x50\x06\x3c\x55\x7e\x8f\x50" },
+        "\x50\x8f\x7e\x55\x3c\x06\x50\x1d\x74\x9a\x66\xfc\x28\xc6\xca\xc0"
+        "\xb0\x05\x74\x6d\x97\x53\x7f\xa8\x5d\x9e\x40\x90\x4e\xfe\xd2\x9d" },
       {	0 }
     };
   gcry_error_t err;
--

-- 
2.0.0
by Jussi Kivilinna | 29 Jun 16:45 2014
Picon

[git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-94-g1b9b00b

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  1b9b00bbe41bbed32563f1102049521e703e72bd (commit)
      from  066f068bd0bc4d8e01f1f18b6153cdc8d2c245d7 (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 1b9b00bbe41bbed32563f1102049521e703e72bd
Author: Jussi Kivilinna <jussi.kivilinna <at> iki.fi>
Date:   Sun Jun 29 17:36:29 2014 +0300

    Speed-up SHA-1 NEON assembly implementation

    * cipher/sha1-armv7-neon.S: Tweak implementation for speed-up.
    --

    Benchmark on Cortex-A8 1008Mhz:

    New:
                    |  nanosecs/byte   mebibytes/sec   cycles/byte
     SHA1           |      7.04 ns/B     135.4 MiB/s      7.10 c/B

    Old:
                    |  nanosecs/byte   mebibytes/sec   cycles/byte
     SHA1           |      7.79 ns/B     122.4 MiB/s      7.85 c/B

    Signed-off-by: Jussi Kivilinna <jussi.kivilinna <at> iki.fi>

diff --git a/cipher/sha1-armv7-neon.S b/cipher/sha1-armv7-neon.S
index 95b677d..f314d8e 100644
--- a/cipher/sha1-armv7-neon.S
+++ b/cipher/sha1-armv7-neon.S
 <at>  <at>  -1,5 +1,5  <at>  <at> 
 /* sha1-armv7-neon.S - ARM/NEON accelerated SHA-1 transform function
- * Copyright (C) 2013 Jussi Kivilinna <jussi.kivilinna <at> iki.fi>
+ * Copyright (C) 2013-2014 Jussi Kivilinna <jussi.kivilinna <at> iki.fi>
  *
  * Based on sha1.c:
  *  Copyright (C) 1998, 2001, 2002, 2003, 2008 Free Software Foundation, Inc.
 <at>  <at>  -26,12 +26,12  <at>  <at> 
     defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \
     defined(HAVE_GCC_INLINE_ASM_NEON) && defined(USE_SHA1)

-.data
-
 .syntax unified
 .fpu neon
 .arm

+.text
+
 #ifdef __PIC__
 #  define GET_DATA_POINTER(reg, name, rtmp) \
 		ldr reg, 1f; \
 <at>  <at>  -69,16 +69,13  <at>  <at>  gcry_sha1_armv7_neon_K_VEC:
 .LK4:	.long K4, K4, K4, K4

 
-.text
-
 /* Register macros */

 #define RSTATE r0
 #define RDATA r1
 #define RNBLKS r2
 #define ROLDSTACK r3
-#define RK lr
-#define RWK r12
+#define RWK lr

 #define _a r4
 #define _b r5
 <at>  <at>  -89,6 +86,7  <at>  <at>  gcry_sha1_armv7_neon_K_VEC:
 #define RT0 r9
 #define RT1 r10
 #define RT2 r11
+#define RT3 r12

 #define W0 q0
 #define W1 q1
 <at>  <at>  -104,7 +102,10  <at>  <at>  gcry_sha1_armv7_neon_K_VEC:
 #define tmp2 q10
 #define tmp3 q11

-#define curK q12
+#define qK1 q12
+#define qK2 q13
+#define qK3 q14
+#define qK4 q15

 
 /* Round function macros. */
 <at>  <at>  -112,43 +113,43  <at>  <at>  gcry_sha1_armv7_neon_K_VEC:
 #define WK_offs(i) (((i) & 15) * 4)

 #define _R_F1(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
-	and RT0, c, b; \
+	ldr RT3, [sp, WK_offs(i)]; \
 		pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	bic RT0, d, b; \
 	add e, e, a, ror #(32 - 5); \
-	ldr RT2, [sp, WK_offs(i)]; \
-	bic RT1, d, b; \
-	add e, RT2; \
+	and RT1, c, b; \
 		pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	add RT0, RT0, RT3; \
+	add e, e, RT1; \
 	ror b, #(32 - 30); \
-	eor RT0, RT1; \
 		pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
-	add e, RT0;
+	add e, e, RT0;

 #define _R_F2(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
-	eor RT0, c, b; \
+	ldr RT3, [sp, WK_offs(i)]; \
 		pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	eor RT0, d, b; \
 	add e, e, a, ror #(32 - 5); \
-	ldr RT2, [sp, WK_offs(i)]; \
-	eor RT0, d; \
+	eor RT0, RT0, c; \
 		pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
-	add e, RT2; \
+	add e, e, RT3; \
 	ror b, #(32 - 30); \
 		pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
-	add e, RT0; \
+	add e, e, RT0; \

 #define _R_F3(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
-	eor RT0, c, b; \
+	ldr RT3, [sp, WK_offs(i)]; \
 		pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	eor RT0, b, c; \
+	and RT1, b, c; \
 	add e, e, a, ror #(32 - 5); \
-	ldr RT2, [sp, WK_offs(i)]; \
-	and RT1, c, b; \
-	and RT0, d; \
-	add e, RT2; \
 		pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	and RT0, RT0, d; \
+	add RT1, RT1, RT3; \
+	add e, e, RT0; \
 	ror b, #(32 - 30); \
-	add e, RT1; \
 		pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
-	add e, RT0;
+	add e, e, RT1;

 #define _R_F4(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
 	_R_F2(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28)
 <at>  <at>  -183,10 +184,10  <at>  <at>  gcry_sha1_armv7_neon_K_VEC:
 	vst1.32   {tmp2, tmp3}, [RWK];				\

 #define WPRECALC_00_15_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	add       RWK, sp, #(WK_offs(0));			\
+	vld1.32   {tmp0, tmp1}, [RDATA]!;			\

 #define WPRECALC_00_15_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	vld1.32   {tmp0, tmp1}, [RDATA]!;			\
+	add       RWK, sp, #(WK_offs(0));			\

 #define WPRECALC_00_15_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
 	vrev32.8  W0, tmp0;		/* big => little */	\
 <at>  <at>  -225,25 +226,25  <at>  <at>  gcry_sha1_armv7_neon_K_VEC:
 /********* Precalc macros for rounds 16-31 ************************************/

 #define WPRECALC_16_31_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	add       RWK, sp, #(WK_offs(i));	\
-
-#define WPRECALC_16_31_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
 	veor      tmp0, tmp0;			\
 	vext.8    W, W_m16, W_m12, #8;		\

-#define WPRECALC_16_31_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
+#define WPRECALC_16_31_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
+	add       RWK, sp, #(WK_offs(i));	\
 	vext.8    tmp0, W_m04, tmp0, #4;	\
+
+#define WPRECALC_16_31_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
+	veor      tmp0, tmp0, W_m16;		\
 	veor.32   W, W, W_m08;			\

 #define WPRECALC_16_31_3(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	veor      tmp0, tmp0, W_m16;		\
 	veor      tmp1, tmp1;			\
+	veor      W, W, tmp0;			\

 #define WPRECALC_16_31_4(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	veor      W, W, tmp0;			\
+	vshl.u32  tmp0, W, #1;			\

 #define WPRECALC_16_31_5(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	vshl.u32  tmp0, W, #1;			\
 	vext.8    tmp1, tmp1, W, #(16-12);	\
 	vshr.u32  W, W, #31;			\

 <at>  <at>  -270,28 +271,28  <at>  <at>  gcry_sha1_armv7_neon_K_VEC:
 /********* Precalc macros for rounds 32-79 ************************************/

 #define WPRECALC_32_79_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	add RWK, sp, #(WK_offs(i&~3)); \
+	veor W, W_m28; \

 #define WPRECALC_32_79_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	veor W, W_m28; \
+	vext.8 tmp0, W_m08, W_m04, #8; \

 #define WPRECALC_32_79_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	vext.8 tmp0, W_m08, W_m04, #8; \
+	veor W, W_m16; \

 #define WPRECALC_32_79_3(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	veor W, W_m16; \
+	veor W, tmp0; \

 #define WPRECALC_32_79_4(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	veor W, tmp0; \
+	add RWK, sp, #(WK_offs(i&~3)); \

 #define WPRECALC_32_79_5(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	vshr.u32 tmp0, W, #30; \
+	vshl.u32 tmp1, W, #2; \

 #define WPRECALC_32_79_6(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	vshl.u32 W, W, #2; \
+	vshr.u32 tmp0, W, #30; \

 #define WPRECALC_32_79_7(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	vorr W, tmp0, W; \
+	vorr W, tmp0, tmp1; \

 #define WPRECALC_32_79_8(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
 	vadd.u32 tmp0, W, curK; \
 <at>  <at>  -326,20 +327,26  <at>  <at>  _gcry_sha1_transform_armv7_neon:
   beq .Ldo_nothing;

   push {r4-r12, lr};
+
+  GET_DATA_POINTER(RT3, .LK_VEC, _a);
   vpush {q4-q7};

   mov ROLDSTACK, sp;
-  GET_DATA_POINTER(RK, .LK_VEC, _a);

   /* Align stack. */
   sub sp, #(16*4);
   and sp, #(~(16-1));

+  vld1.32 {qK1-qK2}, [RT3]!; /* Load K1,K2 */
+
   /* Get the values of the chaining variables. */
   ldm RSTATE, {_a-_e};

+  vld1.32 {qK3-qK4}, [RT3]; /* Load K3,K4 */
+
+#undef curK
+#define curK qK1
   /* Precalc 0-15. */
-  vld1.32 {curK}, [RK]!; /* Load K1. */
   W_PRECALC_00_15();

   b .Loop;
 <at>  <at>  -352,7 +359,8  <at>  <at>  _gcry_sha1_transform_armv7_neon:
   _R( _d, _e, _a, _b, _c, F1,  2, WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 16, W4, W5, W6, W7,
W0, _, _, _ );
   _R( _c, _d, _e, _a, _b, F1,  3, WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,16, W4, W5, W6,
W7, W0, _, _, _ );

-  vld1.32 {curK}, [RK]!; /* Load K2. */
+#undef curK
+#define curK qK2
   _R( _b, _c, _d, _e, _a, F1,  4, WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 20, W3, W4, W5, W6,
W7, _, _, _ );
   _R( _a, _b, _c, _d, _e, F1,  5, WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 20, W3, W4, W5, W6,
W7, _, _, _ );
   _R( _e, _a, _b, _c, _d, F1,  6, WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 20, W3, W4, W5, W6,
W7, _, _, _ );
 <at>  <at>  -371,72 +379,75  <at>  <at>  _gcry_sha1_transform_armv7_neon:
   /* Transform 16-63 + Precalc 32-79. */
   _R( _e, _a, _b, _c, _d, F1, 16, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 32, W0, W1, W2, W3,
W4, W5, W6, W7);
   _R( _d, _e, _a, _b, _c, F1, 17, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 32, W0, W1, W2, W3,
W4, W5, W6, W7);
-  _R( _c, _d, _e, _a, _b, F1, 18, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            32, W0, W1, W2, W3, W4, W5, W6, W7);
+  _R( _c, _d, _e, _a, _b, F1, 18, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 32, W0, W1, W2, W3, W4, W5, W6, W7);
   _R( _b, _c, _d, _e, _a, F1, 19, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 32, W0, W1, W2, W3, W4, W5, W6, W7);

   _R( _a, _b, _c, _d, _e, F2, 20, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 36, W7, W0, W1, W2,
W3, W4, W5, W6);
   _R( _e, _a, _b, _c, _d, F2, 21, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 36, W7, W0, W1, W2,
W3, W4, W5, W6);
-  _R( _d, _e, _a, _b, _c, F2, 22, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            36, W7, W0, W1, W2, W3, W4, W5, W6);
+  _R( _d, _e, _a, _b, _c, F2, 22, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 36, W7, W0, W1, W2, W3, W4, W5, W6);
   _R( _c, _d, _e, _a, _b, F2, 23, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 36, W7, W0, W1, W2, W3, W4, W5, W6);

-  vld1.32 {curK}, [RK]!; /* Load K3. */
+#undef curK
+#define curK qK3
   _R( _b, _c, _d, _e, _a, F2, 24, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 40, W6, W7, W0, W1,
W2, W3, W4, W5);
   _R( _a, _b, _c, _d, _e, F2, 25, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 40, W6, W7, W0, W1,
W2, W3, W4, W5);
-  _R( _e, _a, _b, _c, _d, F2, 26, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            40, W6, W7, W0, W1, W2, W3, W4, W5);
+  _R( _e, _a, _b, _c, _d, F2, 26, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 40, W6, W7, W0, W1, W2, W3, W4, W5);
   _R( _d, _e, _a, _b, _c, F2, 27, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 40, W6, W7, W0, W1, W2, W3, W4, W5);

   _R( _c, _d, _e, _a, _b, F2, 28, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 44, W5, W6, W7, W0,
W1, W2, W3, W4);
   _R( _b, _c, _d, _e, _a, F2, 29, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 44, W5, W6, W7, W0,
W1, W2, W3, W4);
-  _R( _a, _b, _c, _d, _e, F2, 30, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            44, W5, W6, W7, W0, W1, W2, W3, W4);
+  _R( _a, _b, _c, _d, _e, F2, 30, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 44, W5, W6, W7, W0, W1, W2, W3, W4);
   _R( _e, _a, _b, _c, _d, F2, 31, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 44, W5, W6, W7, W0, W1, W2, W3, W4);

   _R( _d, _e, _a, _b, _c, F2, 32, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 48, W4, W5, W6, W7,
W0, W1, W2, W3);
   _R( _c, _d, _e, _a, _b, F2, 33, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 48, W4, W5, W6, W7,
W0, W1, W2, W3);
-  _R( _b, _c, _d, _e, _a, F2, 34, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            48, W4, W5, W6, W7, W0, W1, W2, W3);
+  _R( _b, _c, _d, _e, _a, F2, 34, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 48, W4, W5, W6, W7, W0, W1, W2, W3);
   _R( _a, _b, _c, _d, _e, F2, 35, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 48, W4, W5, W6, W7, W0, W1, W2, W3);

   _R( _e, _a, _b, _c, _d, F2, 36, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 52, W3, W4, W5, W6,
W7, W0, W1, W2);
   _R( _d, _e, _a, _b, _c, F2, 37, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 52, W3, W4, W5, W6,
W7, W0, W1, W2);
-  _R( _c, _d, _e, _a, _b, F2, 38, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            52, W3, W4, W5, W6, W7, W0, W1, W2);
+  _R( _c, _d, _e, _a, _b, F2, 38, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 52, W3, W4, W5, W6, W7, W0, W1, W2);
   _R( _b, _c, _d, _e, _a, F2, 39, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 52, W3, W4, W5, W6, W7, W0, W1, W2);

   _R( _a, _b, _c, _d, _e, F3, 40, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 56, W2, W3, W4, W5,
W6, W7, W0, W1);
   _R( _e, _a, _b, _c, _d, F3, 41, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 56, W2, W3, W4, W5,
W6, W7, W0, W1);
-  _R( _d, _e, _a, _b, _c, F3, 42, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            56, W2, W3, W4, W5, W6, W7, W0, W1);
+  _R( _d, _e, _a, _b, _c, F3, 42, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 56, W2, W3, W4, W5, W6, W7, W0, W1);
   _R( _c, _d, _e, _a, _b, F3, 43, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 56, W2, W3, W4, W5, W6, W7, W0, W1);

-  vld1.32 {curK}, [RK]!; /* Load K4. */
+#undef curK
+#define curK qK4
   _R( _b, _c, _d, _e, _a, F3, 44, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 60, W1, W2, W3, W4,
W5, W6, W7, W0);
   _R( _a, _b, _c, _d, _e, F3, 45, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 60, W1, W2, W3, W4,
W5, W6, W7, W0);
-  _R( _e, _a, _b, _c, _d, F3, 46, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            60, W1, W2, W3, W4, W5, W6, W7, W0);
+  _R( _e, _a, _b, _c, _d, F3, 46, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 60, W1, W2, W3, W4, W5, W6, W7, W0);
   _R( _d, _e, _a, _b, _c, F3, 47, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 60, W1, W2, W3, W4, W5, W6, W7, W0);

   _R( _c, _d, _e, _a, _b, F3, 48, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 64, W0, W1, W2, W3,
W4, W5, W6, W7);
   _R( _b, _c, _d, _e, _a, F3, 49, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 64, W0, W1, W2, W3,
W4, W5, W6, W7);
-  _R( _a, _b, _c, _d, _e, F3, 50, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            64, W0, W1, W2, W3, W4, W5, W6, W7);
+  _R( _a, _b, _c, _d, _e, F3, 50, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 64, W0, W1, W2, W3, W4, W5, W6, W7);
   _R( _e, _a, _b, _c, _d, F3, 51, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 64, W0, W1, W2, W3, W4, W5, W6, W7);

   _R( _d, _e, _a, _b, _c, F3, 52, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 68, W7, W0, W1, W2,
W3, W4, W5, W6);
   _R( _c, _d, _e, _a, _b, F3, 53, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 68, W7, W0, W1, W2,
W3, W4, W5, W6);
-  _R( _b, _c, _d, _e, _a, F3, 54, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            68, W7, W0, W1, W2, W3, W4, W5, W6);
+  _R( _b, _c, _d, _e, _a, F3, 54, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 68, W7, W0, W1, W2, W3, W4, W5, W6);
   _R( _a, _b, _c, _d, _e, F3, 55, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 68, W7, W0, W1, W2, W3, W4, W5, W6);

   _R( _e, _a, _b, _c, _d, F3, 56, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 72, W6, W7, W0, W1,
W2, W3, W4, W5);
   _R( _d, _e, _a, _b, _c, F3, 57, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 72, W6, W7, W0, W1,
W2, W3, W4, W5);
-  _R( _c, _d, _e, _a, _b, F3, 58, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            72, W6, W7, W0, W1, W2, W3, W4, W5);
+  _R( _c, _d, _e, _a, _b, F3, 58, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 72, W6, W7, W0, W1, W2, W3, W4, W5);
   _R( _b, _c, _d, _e, _a, F3, 59, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 72, W6, W7, W0, W1, W2, W3, W4, W5);

-  sub RK, #64;
+  subs RNBLKS, #1;
+
   _R( _a, _b, _c, _d, _e, F4, 60, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 76, W5, W6, W7, W0,
W1, W2, W3, W4);
   _R( _e, _a, _b, _c, _d, F4, 61, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 76, W5, W6, W7, W0,
W1, W2, W3, W4);
-  _R( _d, _e, _a, _b, _c, F4, 62, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            76, W5, W6, W7, W0, W1, W2, W3, W4);
+  _R( _d, _e, _a, _b, _c, F4, 62, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 76, W5, W6, W7, W0, W1, W2, W3, W4);
   _R( _c, _d, _e, _a, _b, F4, 63, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 76, W5, W6, W7, W0, W1, W2, W3, W4);

-  subs RNBLKS, #1;
   beq .Lend;

   /* Transform 64-79 + Precalc 0-15 of next block. */
-  vld1.32 {curK}, [RK]!; /* Load K1. */
+#undef curK
+#define curK qK1
   _R( _b, _c, _d, _e, _a, F4, 64, WPRECALC_00_15_0, dummy, dummy, _, _, _, _, _, _, _, _, _ );
   _R( _a, _b, _c, _d, _e, F4, 65, WPRECALC_00_15_1, dummy, dummy, _, _, _, _, _, _, _, _, _ );
   _R( _e, _a, _b, _c, _d, F4, 66, WPRECALC_00_15_2, dummy, dummy, _, _, _, _, _, _, _, _, _ );
 <at>  <at>  -458,14 +469,13  <at>  <at>  _gcry_sha1_transform_armv7_neon:
   _R( _b, _c, _d, _e, _a, F4, 79, WPRECALC_00_15_11, dummy, WPRECALC_00_15_12, _, _, _, _, _, _, _, _, _ );

   /* Update the chaining variables. */
-  ldm RSTATE, {RT0-RT2};
+  ldm RSTATE, {RT0-RT3};
   add _a, RT0;
-  ldr RT0, [RSTATE, #state_h3];
+  ldr RT0, [RSTATE, #state_h4];
   add _b, RT1;
-  ldr RT1, [RSTATE, #state_h4];
   add _c, RT2;
-  add _d, RT0;
-  add _e, RT1;
+  add _d, RT3;
+  add _e, RT0;
   stm RSTATE, {_a-_e};

   b .Loop;
 <at>  <at>  -493,15 +503,14  <at>  <at>  _gcry_sha1_transform_armv7_neon:
   mov sp, ROLDSTACK;

   /* Update the chaining variables. */
-  ldm RSTATE, {RT0-RT2};
+  ldm RSTATE, {RT0-RT3};
   add _a, RT0;
-  ldr RT0, [RSTATE, #state_h3];
+  ldr RT0, [RSTATE, #state_h4];
   add _b, RT1;
-  ldr RT1, [RSTATE, #state_h4];
   add _c, RT2;
-  add _d, RT0;
+  add _d, RT3;
   vpop {q4-q7};
-  add _e, RT1;
+  add _e, RT0;
   stm RSTATE, {_a-_e};

   /* burn_stack */

-----------------------------------------------------------------------

Summary of changes:
 cipher/sha1-armv7-neon.S |  155 ++++++++++++++++++++++++----------------------
 1 file changed, 82 insertions(+), 73 deletions(-)

hooks/post-receive
--

-- 
The GNU crypto library
http://git.gnupg.org

_______________________________________________
Gnupg-commits mailing list
Gnupg-commits <at> gnupg.org
http://lists.gnupg.org/mailman/listinfo/gnupg-commits
Jussi Kivilinna | 29 Jun 15:36 2014
Picon
Picon

[PATCH] Speed-up SHA-1 NEON assembly implementation

* cipher/sha1-armv7-neon.S: Tweak implementation for speed-up.
--

Benchmark on Cortex-A8 1008Mhz:

New:
                |  nanosecs/byte   mebibytes/sec   cycles/byte
 SHA1           |      7.04 ns/B     135.4 MiB/s      7.10 c/B

Old:
                |  nanosecs/byte   mebibytes/sec   cycles/byte
 SHA1           |      7.79 ns/B     122.4 MiB/s      7.85 c/B

Signed-off-by: Jussi Kivilinna <jussi.kivilinna <at> iki.fi>
---
 cipher/sha1-armv7-neon.S |  155 ++++++++++++++++++++++++----------------------
 1 file changed, 82 insertions(+), 73 deletions(-)

diff --git a/cipher/sha1-armv7-neon.S b/cipher/sha1-armv7-neon.S
index 95b677d..f314d8e 100644
--- a/cipher/sha1-armv7-neon.S
+++ b/cipher/sha1-armv7-neon.S
 <at>  <at>  -1,5 +1,5  <at>  <at> 
 /* sha1-armv7-neon.S - ARM/NEON accelerated SHA-1 transform function
- * Copyright (C) 2013 Jussi Kivilinna <jussi.kivilinna <at> iki.fi>
+ * Copyright (C) 2013-2014 Jussi Kivilinna <jussi.kivilinna <at> iki.fi>
  *
  * Based on sha1.c:
  *  Copyright (C) 1998, 2001, 2002, 2003, 2008 Free Software Foundation, Inc.
 <at>  <at>  -26,12 +26,12  <at>  <at> 
     defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) && \
     defined(HAVE_GCC_INLINE_ASM_NEON) && defined(USE_SHA1)

-.data
-
 .syntax unified
 .fpu neon
 .arm

+.text
+
 #ifdef __PIC__
 #  define GET_DATA_POINTER(reg, name, rtmp) \
 		ldr reg, 1f; \
 <at>  <at>  -69,16 +69,13  <at>  <at>  gcry_sha1_armv7_neon_K_VEC:
 .LK4:	.long K4, K4, K4, K4

 
-.text
-
 /* Register macros */

 #define RSTATE r0
 #define RDATA r1
 #define RNBLKS r2
 #define ROLDSTACK r3
-#define RK lr
-#define RWK r12
+#define RWK lr

 #define _a r4
 #define _b r5
 <at>  <at>  -89,6 +86,7  <at>  <at>  gcry_sha1_armv7_neon_K_VEC:
 #define RT0 r9
 #define RT1 r10
 #define RT2 r11
+#define RT3 r12

 #define W0 q0
 #define W1 q1
 <at>  <at>  -104,7 +102,10  <at>  <at>  gcry_sha1_armv7_neon_K_VEC:
 #define tmp2 q10
 #define tmp3 q11

-#define curK q12
+#define qK1 q12
+#define qK2 q13
+#define qK3 q14
+#define qK4 q15

 
 /* Round function macros. */
 <at>  <at>  -112,43 +113,43  <at>  <at>  gcry_sha1_armv7_neon_K_VEC:
 #define WK_offs(i) (((i) & 15) * 4)

 #define _R_F1(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
-	and RT0, c, b; \
+	ldr RT3, [sp, WK_offs(i)]; \
 		pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	bic RT0, d, b; \
 	add e, e, a, ror #(32 - 5); \
-	ldr RT2, [sp, WK_offs(i)]; \
-	bic RT1, d, b; \
-	add e, RT2; \
+	and RT1, c, b; \
 		pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	add RT0, RT0, RT3; \
+	add e, e, RT1; \
 	ror b, #(32 - 30); \
-	eor RT0, RT1; \
 		pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
-	add e, RT0;
+	add e, e, RT0;

 #define _R_F2(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
-	eor RT0, c, b; \
+	ldr RT3, [sp, WK_offs(i)]; \
 		pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	eor RT0, d, b; \
 	add e, e, a, ror #(32 - 5); \
-	ldr RT2, [sp, WK_offs(i)]; \
-	eor RT0, d; \
+	eor RT0, RT0, c; \
 		pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
-	add e, RT2; \
+	add e, e, RT3; \
 	ror b, #(32 - 30); \
 		pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
-	add e, RT0; \
+	add e, e, RT0; \

 #define _R_F3(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
-	eor RT0, c, b; \
+	ldr RT3, [sp, WK_offs(i)]; \
 		pre1(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	eor RT0, b, c; \
+	and RT1, b, c; \
 	add e, e, a, ror #(32 - 5); \
-	ldr RT2, [sp, WK_offs(i)]; \
-	and RT1, c, b; \
-	and RT0, d; \
-	add e, RT2; \
 		pre2(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
+	and RT0, RT0, d; \
+	add RT1, RT1, RT3; \
+	add e, e, RT0; \
 	ror b, #(32 - 30); \
-	add e, RT1; \
 		pre3(i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28); \
-	add e, RT0;
+	add e, e, RT1;

 #define _R_F4(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28) \
 	_R_F2(a,b,c,d,e,i,pre1,pre2,pre3,i16,W,W_m04,W_m08,W_m12,W_m16,W_m20,W_m24,W_m28)
 <at>  <at>  -183,10 +184,10  <at>  <at>  gcry_sha1_armv7_neon_K_VEC:
 	vst1.32   {tmp2, tmp3}, [RWK];				\

 #define WPRECALC_00_15_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	add       RWK, sp, #(WK_offs(0));			\
+	vld1.32   {tmp0, tmp1}, [RDATA]!;			\

 #define WPRECALC_00_15_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	vld1.32   {tmp0, tmp1}, [RDATA]!;			\
+	add       RWK, sp, #(WK_offs(0));			\

 #define WPRECALC_00_15_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
 	vrev32.8  W0, tmp0;		/* big => little */	\
 <at>  <at>  -225,25 +226,25  <at>  <at>  gcry_sha1_armv7_neon_K_VEC:
 /********* Precalc macros for rounds 16-31 ************************************/

 #define WPRECALC_16_31_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	add       RWK, sp, #(WK_offs(i));	\
-
-#define WPRECALC_16_31_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
 	veor      tmp0, tmp0;			\
 	vext.8    W, W_m16, W_m12, #8;		\

-#define WPRECALC_16_31_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
+#define WPRECALC_16_31_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
+	add       RWK, sp, #(WK_offs(i));	\
 	vext.8    tmp0, W_m04, tmp0, #4;	\
+
+#define WPRECALC_16_31_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
+	veor      tmp0, tmp0, W_m16;		\
 	veor.32   W, W, W_m08;			\

 #define WPRECALC_16_31_3(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	veor      tmp0, tmp0, W_m16;		\
 	veor      tmp1, tmp1;			\
+	veor      W, W, tmp0;			\

 #define WPRECALC_16_31_4(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	veor      W, W, tmp0;			\
+	vshl.u32  tmp0, W, #1;			\

 #define WPRECALC_16_31_5(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	vshl.u32  tmp0, W, #1;			\
 	vext.8    tmp1, tmp1, W, #(16-12);	\
 	vshr.u32  W, W, #31;			\

 <at>  <at>  -270,28 +271,28  <at>  <at>  gcry_sha1_armv7_neon_K_VEC:
 /********* Precalc macros for rounds 32-79 ************************************/

 #define WPRECALC_32_79_0(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	add RWK, sp, #(WK_offs(i&~3)); \
+	veor W, W_m28; \

 #define WPRECALC_32_79_1(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	veor W, W_m28; \
+	vext.8 tmp0, W_m08, W_m04, #8; \

 #define WPRECALC_32_79_2(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	vext.8 tmp0, W_m08, W_m04, #8; \
+	veor W, W_m16; \

 #define WPRECALC_32_79_3(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	veor W, W_m16; \
+	veor W, tmp0; \

 #define WPRECALC_32_79_4(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	veor W, tmp0; \
+	add RWK, sp, #(WK_offs(i&~3)); \

 #define WPRECALC_32_79_5(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	vshr.u32 tmp0, W, #30; \
+	vshl.u32 tmp1, W, #2; \

 #define WPRECALC_32_79_6(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	vshl.u32 W, W, #2; \
+	vshr.u32 tmp0, W, #30; \

 #define WPRECALC_32_79_7(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
-	vorr W, tmp0, W; \
+	vorr W, tmp0, tmp1; \

 #define WPRECALC_32_79_8(i, W, W_m04, W_m08, W_m12, W_m16, W_m20, W_m24, W_m28) \
 	vadd.u32 tmp0, W, curK; \
 <at>  <at>  -326,20 +327,26  <at>  <at>  _gcry_sha1_transform_armv7_neon:
   beq .Ldo_nothing;

   push {r4-r12, lr};
+
+  GET_DATA_POINTER(RT3, .LK_VEC, _a);
   vpush {q4-q7};

   mov ROLDSTACK, sp;
-  GET_DATA_POINTER(RK, .LK_VEC, _a);

   /* Align stack. */
   sub sp, #(16*4);
   and sp, #(~(16-1));

+  vld1.32 {qK1-qK2}, [RT3]!; /* Load K1,K2 */
+
   /* Get the values of the chaining variables. */
   ldm RSTATE, {_a-_e};

+  vld1.32 {qK3-qK4}, [RT3]; /* Load K3,K4 */
+
+#undef curK
+#define curK qK1
   /* Precalc 0-15. */
-  vld1.32 {curK}, [RK]!; /* Load K1. */
   W_PRECALC_00_15();

   b .Loop;
 <at>  <at>  -352,7 +359,8  <at>  <at>  _gcry_sha1_transform_armv7_neon:
   _R( _d, _e, _a, _b, _c, F1,  2, WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 16, W4, W5, W6, W7,
W0, _, _, _ );
   _R( _c, _d, _e, _a, _b, F1,  3, WPRECALC_16_31_9, WPRECALC_16_31_10,WPRECALC_16_31_11,16, W4, W5, W6,
W7, W0, _, _, _ );

-  vld1.32 {curK}, [RK]!; /* Load K2. */
+#undef curK
+#define curK qK2
   _R( _b, _c, _d, _e, _a, F1,  4, WPRECALC_16_31_0, WPRECALC_16_31_1, WPRECALC_16_31_2, 20, W3, W4, W5, W6,
W7, _, _, _ );
   _R( _a, _b, _c, _d, _e, F1,  5, WPRECALC_16_31_3, WPRECALC_16_31_4, WPRECALC_16_31_5, 20, W3, W4, W5, W6,
W7, _, _, _ );
   _R( _e, _a, _b, _c, _d, F1,  6, WPRECALC_16_31_6, WPRECALC_16_31_7, WPRECALC_16_31_8, 20, W3, W4, W5, W6,
W7, _, _, _ );
 <at>  <at>  -371,72 +379,75  <at>  <at>  _gcry_sha1_transform_armv7_neon:
   /* Transform 16-63 + Precalc 32-79. */
   _R( _e, _a, _b, _c, _d, F1, 16, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 32, W0, W1, W2, W3,
W4, W5, W6, W7);
   _R( _d, _e, _a, _b, _c, F1, 17, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 32, W0, W1, W2, W3,
W4, W5, W6, W7);
-  _R( _c, _d, _e, _a, _b, F1, 18, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            32, W0, W1, W2, W3, W4, W5, W6, W7);
+  _R( _c, _d, _e, _a, _b, F1, 18, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 32, W0, W1, W2, W3, W4, W5, W6, W7);
   _R( _b, _c, _d, _e, _a, F1, 19, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 32, W0, W1, W2, W3, W4, W5, W6, W7);

   _R( _a, _b, _c, _d, _e, F2, 20, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 36, W7, W0, W1, W2,
W3, W4, W5, W6);
   _R( _e, _a, _b, _c, _d, F2, 21, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 36, W7, W0, W1, W2,
W3, W4, W5, W6);
-  _R( _d, _e, _a, _b, _c, F2, 22, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            36, W7, W0, W1, W2, W3, W4, W5, W6);
+  _R( _d, _e, _a, _b, _c, F2, 22, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 36, W7, W0, W1, W2, W3, W4, W5, W6);
   _R( _c, _d, _e, _a, _b, F2, 23, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 36, W7, W0, W1, W2, W3, W4, W5, W6);

-  vld1.32 {curK}, [RK]!; /* Load K3. */
+#undef curK
+#define curK qK3
   _R( _b, _c, _d, _e, _a, F2, 24, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 40, W6, W7, W0, W1,
W2, W3, W4, W5);
   _R( _a, _b, _c, _d, _e, F2, 25, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 40, W6, W7, W0, W1,
W2, W3, W4, W5);
-  _R( _e, _a, _b, _c, _d, F2, 26, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            40, W6, W7, W0, W1, W2, W3, W4, W5);
+  _R( _e, _a, _b, _c, _d, F2, 26, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 40, W6, W7, W0, W1, W2, W3, W4, W5);
   _R( _d, _e, _a, _b, _c, F2, 27, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 40, W6, W7, W0, W1, W2, W3, W4, W5);

   _R( _c, _d, _e, _a, _b, F2, 28, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 44, W5, W6, W7, W0,
W1, W2, W3, W4);
   _R( _b, _c, _d, _e, _a, F2, 29, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 44, W5, W6, W7, W0,
W1, W2, W3, W4);
-  _R( _a, _b, _c, _d, _e, F2, 30, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            44, W5, W6, W7, W0, W1, W2, W3, W4);
+  _R( _a, _b, _c, _d, _e, F2, 30, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 44, W5, W6, W7, W0, W1, W2, W3, W4);
   _R( _e, _a, _b, _c, _d, F2, 31, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 44, W5, W6, W7, W0, W1, W2, W3, W4);

   _R( _d, _e, _a, _b, _c, F2, 32, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 48, W4, W5, W6, W7,
W0, W1, W2, W3);
   _R( _c, _d, _e, _a, _b, F2, 33, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 48, W4, W5, W6, W7,
W0, W1, W2, W3);
-  _R( _b, _c, _d, _e, _a, F2, 34, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            48, W4, W5, W6, W7, W0, W1, W2, W3);
+  _R( _b, _c, _d, _e, _a, F2, 34, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 48, W4, W5, W6, W7, W0, W1, W2, W3);
   _R( _a, _b, _c, _d, _e, F2, 35, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 48, W4, W5, W6, W7, W0, W1, W2, W3);

   _R( _e, _a, _b, _c, _d, F2, 36, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 52, W3, W4, W5, W6,
W7, W0, W1, W2);
   _R( _d, _e, _a, _b, _c, F2, 37, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 52, W3, W4, W5, W6,
W7, W0, W1, W2);
-  _R( _c, _d, _e, _a, _b, F2, 38, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            52, W3, W4, W5, W6, W7, W0, W1, W2);
+  _R( _c, _d, _e, _a, _b, F2, 38, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 52, W3, W4, W5, W6, W7, W0, W1, W2);
   _R( _b, _c, _d, _e, _a, F2, 39, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 52, W3, W4, W5, W6, W7, W0, W1, W2);

   _R( _a, _b, _c, _d, _e, F3, 40, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 56, W2, W3, W4, W5,
W6, W7, W0, W1);
   _R( _e, _a, _b, _c, _d, F3, 41, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 56, W2, W3, W4, W5,
W6, W7, W0, W1);
-  _R( _d, _e, _a, _b, _c, F3, 42, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            56, W2, W3, W4, W5, W6, W7, W0, W1);
+  _R( _d, _e, _a, _b, _c, F3, 42, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 56, W2, W3, W4, W5, W6, W7, W0, W1);
   _R( _c, _d, _e, _a, _b, F3, 43, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 56, W2, W3, W4, W5, W6, W7, W0, W1);

-  vld1.32 {curK}, [RK]!; /* Load K4. */
+#undef curK
+#define curK qK4
   _R( _b, _c, _d, _e, _a, F3, 44, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 60, W1, W2, W3, W4,
W5, W6, W7, W0);
   _R( _a, _b, _c, _d, _e, F3, 45, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 60, W1, W2, W3, W4,
W5, W6, W7, W0);
-  _R( _e, _a, _b, _c, _d, F3, 46, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            60, W1, W2, W3, W4, W5, W6, W7, W0);
+  _R( _e, _a, _b, _c, _d, F3, 46, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 60, W1, W2, W3, W4, W5, W6, W7, W0);
   _R( _d, _e, _a, _b, _c, F3, 47, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 60, W1, W2, W3, W4, W5, W6, W7, W0);

   _R( _c, _d, _e, _a, _b, F3, 48, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 64, W0, W1, W2, W3,
W4, W5, W6, W7);
   _R( _b, _c, _d, _e, _a, F3, 49, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 64, W0, W1, W2, W3,
W4, W5, W6, W7);
-  _R( _a, _b, _c, _d, _e, F3, 50, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            64, W0, W1, W2, W3, W4, W5, W6, W7);
+  _R( _a, _b, _c, _d, _e, F3, 50, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 64, W0, W1, W2, W3, W4, W5, W6, W7);
   _R( _e, _a, _b, _c, _d, F3, 51, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 64, W0, W1, W2, W3, W4, W5, W6, W7);

   _R( _d, _e, _a, _b, _c, F3, 52, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 68, W7, W0, W1, W2,
W3, W4, W5, W6);
   _R( _c, _d, _e, _a, _b, F3, 53, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 68, W7, W0, W1, W2,
W3, W4, W5, W6);
-  _R( _b, _c, _d, _e, _a, F3, 54, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            68, W7, W0, W1, W2, W3, W4, W5, W6);
+  _R( _b, _c, _d, _e, _a, F3, 54, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 68, W7, W0, W1, W2, W3, W4, W5, W6);
   _R( _a, _b, _c, _d, _e, F3, 55, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 68, W7, W0, W1, W2, W3, W4, W5, W6);

   _R( _e, _a, _b, _c, _d, F3, 56, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 72, W6, W7, W0, W1,
W2, W3, W4, W5);
   _R( _d, _e, _a, _b, _c, F3, 57, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 72, W6, W7, W0, W1,
W2, W3, W4, W5);
-  _R( _c, _d, _e, _a, _b, F3, 58, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            72, W6, W7, W0, W1, W2, W3, W4, W5);
+  _R( _c, _d, _e, _a, _b, F3, 58, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 72, W6, W7, W0, W1, W2, W3, W4, W5);
   _R( _b, _c, _d, _e, _a, F3, 59, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 72, W6, W7, W0, W1, W2, W3, W4, W5);

-  sub RK, #64;
+  subs RNBLKS, #1;
+
   _R( _a, _b, _c, _d, _e, F4, 60, WPRECALC_32_79_0, WPRECALC_32_79_1, WPRECALC_32_79_2, 76, W5, W6, W7, W0,
W1, W2, W3, W4);
   _R( _e, _a, _b, _c, _d, F4, 61, WPRECALC_32_79_3, WPRECALC_32_79_4, WPRECALC_32_79_5, 76, W5, W6, W7, W0,
W1, W2, W3, W4);
-  _R( _d, _e, _a, _b, _c, F4, 62, WPRECALC_32_79_6, WPRECALC_32_79_7, dummy,            76, W5, W6, W7, W0, W1, W2, W3, W4);
+  _R( _d, _e, _a, _b, _c, F4, 62, WPRECALC_32_79_6, dummy,            WPRECALC_32_79_7, 76, W5, W6, W7, W0, W1, W2, W3, W4);
   _R( _c, _d, _e, _a, _b, F4, 63, WPRECALC_32_79_8, dummy,            WPRECALC_32_79_9, 76, W5, W6, W7, W0, W1, W2, W3, W4);

-  subs RNBLKS, #1;
   beq .Lend;

   /* Transform 64-79 + Precalc 0-15 of next block. */
-  vld1.32 {curK}, [RK]!; /* Load K1. */
+#undef curK
+#define curK qK1
   _R( _b, _c, _d, _e, _a, F4, 64, WPRECALC_00_15_0, dummy, dummy, _, _, _, _, _, _, _, _, _ );
   _R( _a, _b, _c, _d, _e, F4, 65, WPRECALC_00_15_1, dummy, dummy, _, _, _, _, _, _, _, _, _ );
   _R( _e, _a, _b, _c, _d, F4, 66, WPRECALC_00_15_2, dummy, dummy, _, _, _, _, _, _, _, _, _ );
 <at>  <at>  -458,14 +469,13  <at>  <at>  _gcry_sha1_transform_armv7_neon:
   _R( _b, _c, _d, _e, _a, F4, 79, WPRECALC_00_15_11, dummy, WPRECALC_00_15_12, _, _, _, _, _, _, _, _, _ );

   /* Update the chaining variables. */
-  ldm RSTATE, {RT0-RT2};
+  ldm RSTATE, {RT0-RT3};
   add _a, RT0;
-  ldr RT0, [RSTATE, #state_h3];
+  ldr RT0, [RSTATE, #state_h4];
   add _b, RT1;
-  ldr RT1, [RSTATE, #state_h4];
   add _c, RT2;
-  add _d, RT0;
-  add _e, RT1;
+  add _d, RT3;
+  add _e, RT0;
   stm RSTATE, {_a-_e};

   b .Loop;
 <at>  <at>  -493,15 +503,14  <at>  <at>  _gcry_sha1_transform_armv7_neon:
   mov sp, ROLDSTACK;

   /* Update the chaining variables. */
-  ldm RSTATE, {RT0-RT2};
+  ldm RSTATE, {RT0-RT3};
   add _a, RT0;
-  ldr RT0, [RSTATE, #state_h3];
+  ldr RT0, [RSTATE, #state_h4];
   add _b, RT1;
-  ldr RT1, [RSTATE, #state_h4];
   add _c, RT2;
-  add _d, RT0;
+  add _d, RT3;
   vpop {q4-q7};
-  add _e, RT1;
+  add _e, RT0;
   stm RSTATE, {_a-_e};

   /* burn_stack */
by Dmitry Eremin-Solenikov | 28 Jun 10:52 2014
Picon

[git] GCRYPT - branch, master, updated. libgcrypt-1.6.0-93-g066f068

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  066f068bd0bc4d8e01f1f18b6153cdc8d2c245d7 (commit)
       via  7aeba6c449169926076df83b01ddbfa6b41fe411 (commit)
       via  b78d504fa8745b8b04589acbbcf7dd5fe9279d13 (commit)
       via  7533b2ad46f42e98d9dba52e88e79c0311d2d3b7 (commit)
       via  25d6af77e2336b5979ddbe8b90978fe5b61dfaf9 (commit)
       via  5ee35a04362c94e680ef3633fa83b72e0aee8626 (commit)
       via  fb074d113fcbf66a5c20592625cb19051f3430f5 (commit)
       via  164738a0292b3f32c7747099ad9cadace58e5eda (commit)
       via  34a58010000288515636706811c3837f32957b2e (commit)
       via  8b221cf5ce233c8c49a4e4ecebb70d523fc37837 (commit)
      from  f14fb5b427b5159fcd9603d2b3cde936889cf430 (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 066f068bd0bc4d8e01f1f18b6153cdc8d2c245d7
Author: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>
Date:   Fri Jun 6 22:48:36 2014 +0400

    gostr3411_94: rewrite to use u32 mathematic
    
    * cipher/gost28147.c (_gcry_gost_enc_data): New.
    * cipher/gostr3411-94.c: Rewrite implementation to use u32 mathematic
      internally.
    * cipher/gost28147.c (_gcry_gost_enc_one): Remove.
    
    --
    On my box (Core2 Duo, i386) this highly improves GOST R 34.11-94 speed.
    
    Before:
     GOSTR3411_94   |     55.04 ns/B     17.33 MiB/s         - c/B
    
    After:
     GOSTR3411_94   |     36.70 ns/B     25.99 MiB/s         - c/B
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>

diff --git a/cipher/gost.h b/cipher/gost.h
index caaf34b..025119c 100644
--- a/cipher/gost.h
+++ b/cipher/gost.h
 <at>  <at>  -26,7 +26,7  <at>  <at>  typedef struct {
 } GOST28147_context;
 
 /* This is a simple interface that will be used by GOST R 34.11-94 */
-extern unsigned int _gcry_gost_enc_one (GOST28147_context *c, const byte *key,
-    byte *out, byte *in, int cryptopro);
+unsigned int _gcry_gost_enc_data (GOST28147_context *c, const u32 *key,
+    u32 *o1, u32 *o2, u32 n1, u32 n2, int cryptopro);
 
 #endif
diff --git a/cipher/gost28147.c b/cipher/gost28147.c
index af3911e..4ff80b4 100644
--- a/cipher/gost28147.c
+++ b/cipher/gost28147.c
 <at>  <at>  -69,13 +69,9  <at>  <at>  gost_val (GOST28147_context *ctx, u32 cm1, int subkey)
 }
 
 static unsigned int
-gost_encrypt_block (void *c, byte *outbuf, const byte *inbuf)
+_gost_encrypt_data (void *c, u32 *o1, u32 *o2, u32 n1, u32 n2)
 {
   GOST28147_context *ctx = c;
-  u32 n1, n2;
-
-  n1 = buf_get_le32 (inbuf);
-  n2 = buf_get_le32 (inbuf+4);
 
   n2 ^= gost_val (ctx, n1, 0); n1 ^= gost_val (ctx, n2, 1);
   n2 ^= gost_val (ctx, n1, 2); n1 ^= gost_val (ctx, n2, 3);
 <at>  <at>  -97,23 +93,41  <at>  <at>  gost_encrypt_block (void *c, byte *outbuf, const byte *inbuf)
   n2 ^= gost_val (ctx, n1, 3); n1 ^= gost_val (ctx, n2, 2);
   n2 ^= gost_val (ctx, n1, 1); n1 ^= gost_val (ctx, n2, 0);
 
-  buf_put_le32 (outbuf+0, n2);
-  buf_put_le32 (outbuf+4, n1);
+  *o1 = n2;
+  *o2 = n1;
 
   return /* burn_stack */ 4*sizeof(void*) /* func call */ +
                           3*sizeof(void*) /* stack */ +
                           4*sizeof(void*) /* gost_val call */;
 }
 
-unsigned int _gcry_gost_enc_one (GOST28147_context *c, const byte *key,
-    byte *out, byte *in, int cryptopro)
+static unsigned int
+gost_encrypt_block (void *c, byte *outbuf, const byte *inbuf)
+{
+  GOST28147_context *ctx = c;
+  u32 n1, n2;
+  unsigned int burn;
+
+  n1 = buf_get_le32 (inbuf);
+  n2 = buf_get_le32 (inbuf+4);
+
+  burn = _gost_encrypt_data(ctx, &n1, &n2, n1, n2);
+
+  buf_put_le32 (outbuf+0, n1);
+  buf_put_le32 (outbuf+4, n2);
+
+  return /* burn_stack */ burn + 6*sizeof(void*) /* func call */;
+}
+
+unsigned int _gcry_gost_enc_data (GOST28147_context *c, const u32 *key,
+    u32 *o1, u32 *o2, u32 n1, u32 n2, int cryptopro)
 {
   if (cryptopro)
     c->sbox = sbox_CryptoPro_3411;
   else
     c->sbox = sbox_test_3411;
-  gost_setkey (c, key, 32);
-  return gost_encrypt_block (c, out, in) + 5 * sizeof(void *);
+  memcpy (c->key, key, 8*4);
+  return _gost_encrypt_data (c, o1, o2, n1, n2) + 7 * sizeof(void *);
 }
 
 static unsigned int
diff --git a/cipher/gostr3411-94.c b/cipher/gostr3411-94.c
index 9d065fb..91e5b4c 100644
--- a/cipher/gostr3411-94.c
+++ b/cipher/gostr3411-94.c
 <at>  <at>  -25,6 +25,7  <at>  <at> 
 
 #include "g10lib.h"
 #include "bithelp.h"
+#include "bufhelp.h"
 #include "cipher.h"
 #include "hash-common.h"
 
 <at>  <at>  -35,8 +36,11  <at>  <at> 
 typedef struct {
   gcry_md_block_ctx_t bctx;
   GOST28147_context hd;
-  byte h[32];
-  byte sigma[32];
+  union {
+    u32 h[8];
+    byte result[32];
+  };
+  u32 sigma[8];
   u32 len;
   int cryptopro;
 } GOSTR3411_CONTEXT;
 <at>  <at>  -71,102 +75,122  <at>  <at>  gost3411_cp_init (void *context, unsigned int flags)
 }
 
 static void
-do_p (unsigned char *p, unsigned char *u, unsigned char *v)
+do_p (u32 *p, u32 *u, u32 *v)
 {
-  int i, k;
+  int k;
+  u32 t[8];
+
   for (k = 0; k < 8; k++)
+    t[k] = u[k] ^ v[k];
+
+  for (k = 0; k < 4; k++)
     {
-      for (i = 0; i < 4; i++)
-        {
-          p[i + 4 * k] = u[8 * i + k] ^ v[8 * i + k];
-        }
+          p[k+0] = ((t[0] >> (8*k)) & 0xff) << 0 |
+                   ((t[2] >> (8*k)) & 0xff) << 8 |
+                   ((t[4] >> (8*k)) & 0xff) << 16 |
+                   ((t[6] >> (8*k)) & 0xff) << 24;
+          p[k+4] = ((t[1] >> (8*k)) & 0xff) << 0 |
+                   ((t[3] >> (8*k)) & 0xff) << 8 |
+                   ((t[5] >> (8*k)) & 0xff) << 16 |
+                   ((t[7] >> (8*k)) & 0xff) << 24;
     }
 }
 
 static void
-do_a (unsigned char *u)
+do_a (u32 *u)
 {
-  unsigned char temp[8];
+  u32 t[2];
   int i;
-  memcpy (temp, u, 8);
-  memmove (u, u+8, 24);
-  for (i = 0; i < 8; i++)
-    {
-      u[24 + i] = u[i] ^ temp[i];
-    }
+  memcpy(t, u, 2*4);
+  for (i = 0; i < 6; i++)
+    u[i] = u[i+2];
+  u[6] = u[0] ^ t[0];
+  u[7] = u[1] ^ t[1];
 }
 /* apply do_a twice: 1 2 3 4 -> 3 4 1^2 2^3 */
 static void
-do_a2 (unsigned char *u)
+do_a2 (u32 *u)
 {
-  unsigned char temp[16];
+  u32 t[4];
   int i;
-  memcpy (temp, u, 16);
-  memcpy (u, u + 16, 16);
-  for (i = 0; i < 8; i++)
+  memcpy (t, u, 16);
+  memcpy (u, u + 4, 16);
+  for (i = 0; i < 2; i++)
     {
-      u[16 + i] = temp[i] ^ temp[8 + i];
-      u[24 + i] =    u[i] ^ temp[8 + i];
+      u[4+i] = t[i] ^ t[i + 2];
+      u[6+i] = u[i] ^ t[i + 2];
     }
 }
 
 static void
-do_apply_c2 (unsigned char *u)
+do_apply_c2 (u32 *u)
 {
-  u[ 1] ^= 0xff;
-  u[ 3] ^= 0xff;
-  u[ 5] ^= 0xff;
-  u[ 7] ^= 0xff;
-
-  u[ 8] ^= 0xff;
-  u[10] ^= 0xff;
-  u[12] ^= 0xff;
-  u[14] ^= 0xff;
-
-  u[17] ^= 0xff;
-  u[18] ^= 0xff;
-  u[20] ^= 0xff;
-  u[23] ^= 0xff;
-
-  u[24] ^= 0xff;
-  u[28] ^= 0xff;
-  u[29] ^= 0xff;
-  u[31] ^= 0xff;
+  u[ 0] ^= 0xff00ff00;
+  u[ 1] ^= 0xff00ff00;
+  u[ 2] ^= 0x00ff00ff;
+  u[ 3] ^= 0x00ff00ff;
+  u[ 4] ^= 0x00ffff00;
+  u[ 5] ^= 0xff0000ff;
+  u[ 6] ^= 0x000000ff;
+  u[ 7] ^= 0xff00ffff;
 }
 
-#define do_phi_step(e, i) \
-  e[(0 + 2*i) % 32] ^= e[(2 + 2*i) % 32] ^ e[(4 + 2*i) % 32] ^ e[(6 + 2*i) % 32] ^ e[(24 + 2*i) % 32] ^ e[(30 + 2*i) % 32]; \
-  e[(1 + 2*i) % 32] ^= e[(3 + 2*i) % 32] ^ e[(5 + 2*i) % 32] ^ e[(7 + 2*i) % 32] ^ e[(25 + 2*i) % 32] ^ e[(31 + 2*i) % 32];
+#define do_chi_step12(e) \
+  e[6] ^= ((e[6] >> 16) ^ e[7] ^ (e[7] >> 16) ^ e[4] ^ (e[5] >>16)) & 0xffff;
+
+#define do_chi_step13(e) \
+  e[6] ^= ((e[7] ^ (e[7] >> 16) ^ e[0] ^ (e[4] >> 16) ^ e[6]) & 0xffff) << 16;
+
+#define do_chi_doublestep(e, i) \
+  e[i] ^= (e[i] >> 16) ^ (e[(i+1)%8] << 16) ^ e[(i+1)%8] ^ (e[(i+1)%8] >> 16) ^ (e[(i+2)%8] << 16) ^ e[(i+6)%8] ^ (e[(i+7)%8] >> 16); \
+  e[i] ^= (e[i] << 16);
 
 static void
-do_phi_submix (unsigned char *e, unsigned char *x, int round)
+do_chi_submix12 (u32 *e, u32 *x)
 {
-  int i;
-  round *= 2;
-  for (i = 0; i < 32; i++)
-    {
-      e[(i + round) % 32] ^= x[i];
-    }
+  e[6] ^= x[0];
+  e[7] ^= x[1];
+  e[0] ^= x[2];
+  e[1] ^= x[3];
+  e[2] ^= x[4];
+  e[3] ^= x[5];
+  e[4] ^= x[6];
+  e[5] ^= x[7];
+}
+
+static void
+do_chi_submix13 (u32 *e, u32 *x)
+{
+  e[6] ^= (x[0] << 16) | (x[7] >> 16);
+  e[7] ^= (x[1] << 16) | (x[0] >> 16);
+  e[0] ^= (x[2] << 16) | (x[1] >> 16);
+  e[1] ^= (x[3] << 16) | (x[2] >> 16);
+  e[2] ^= (x[4] << 16) | (x[3] >> 16);
+  e[3] ^= (x[5] << 16) | (x[4] >> 16);
+  e[4] ^= (x[6] << 16) | (x[5] >> 16);
+  e[5] ^= (x[7] << 16) | (x[6] >> 16);
 }
 
 static void
-do_add (unsigned char *s, unsigned char *a)
+do_add (u32 *s, u32 *a)
 {
-  unsigned temp = 0;
+  u32 carry = 0;
   int i;
 
-  for (i = 0; i < 32; i++)
+  for (i = 0; i < 8; i++)
     {
-      temp = s[i] + a[i] + (temp >> 8);
-      s[i] = temp & 0xff;
+      u32 op = carry + a[i];
+      s[i] += op;
+      carry = (a[i] > op) || (op > s[i]);
     }
 }
 
 static unsigned int
-do_hash_step (GOSTR3411_CONTEXT *hd, unsigned char *h, unsigned char *m)
+do_hash_step (GOSTR3411_CONTEXT *hd, u32 *h, u32 *m)
 {
-  unsigned char u[32], v[32], s[32];
-  unsigned char k[32];
+  u32 u[8], v[8];
+  u32 s[8];
+  u32 k[8];
   unsigned int burn;
   int i;
 
 <at>  <at>  -176,7 +200,7  <at>  <at>  do_hash_step (GOSTR3411_CONTEXT *hd, unsigned char *h, unsigned char *m)
   for (i = 0; i < 4; i++) {
     do_p (k, u, v);
 
-    burn = _gcry_gost_enc_one (&hd->hd, k, s + i*8, h + i*8, hd->cryptopro);
+    burn = _gcry_gost_enc_data (&hd->hd, k, &s[2*i], &s[2*i+1], h[2*i], h[2*i+1], hd->cryptopro);
 
     do_a (u);
     if (i == 1)
 <at>  <at>  -186,33 +210,26  <at>  <at>  do_hash_step (GOSTR3411_CONTEXT *hd, unsigned char *h, unsigned char *m)
 
   for (i = 0; i < 5; i++)
     {
-      do_phi_step (s, 0);
-      do_phi_step (s, 1);
-      do_phi_step (s, 2);
-      do_phi_step (s, 3);
-      do_phi_step (s, 4);
-      do_phi_step (s, 5);
-      do_phi_step (s, 6);
-      do_phi_step (s, 7);
-      do_phi_step (s, 8);
-      do_phi_step (s, 9);
+      do_chi_doublestep (s, 0);
+      do_chi_doublestep (s, 1);
+      do_chi_doublestep (s, 2);
+      do_chi_doublestep (s, 3);
+      do_chi_doublestep (s, 4);
       /* That is in total 12 + 1 + 61 = 74 = 16 * 4 + 10 rounds */
       if (i == 4)
         break;
-      do_phi_step (s, 10);
-      do_phi_step (s, 11);
+      do_chi_doublestep (s, 5);
       if (i == 0)
-        do_phi_submix(s, m, 12);
-      do_phi_step (s, 12);
+        do_chi_submix12(s, m);
+      do_chi_step12 (s);
       if (i == 0)
-        do_phi_submix(s, h, 13);
-      do_phi_step (s, 13);
-      do_phi_step (s, 14);
-      do_phi_step (s, 15);
+        do_chi_submix13(s, h);
+      do_chi_step13 (s);
+      do_chi_doublestep (s, 7);
     }
 
-  memcpy (h, s+20, 12);
-  memcpy (h+12, s, 20);
+  memcpy (h, s+5, 12);
+  memcpy (h+3, s, 20);
 
   return /* burn_stack */ 4 * sizeof(void*) /* func call (ret addr + args) */ +
                           4 * 32 + 2 * sizeof(int) /* stack */ +
 <at>  <at>  -221,15 +238,16  <at>  <at>  do_hash_step (GOSTR3411_CONTEXT *hd, unsigned char *h, unsigned char *m)
                               16 + sizeof(int) /* do_a2 stack */ );
 }
 
-
 static unsigned int
 transform_blk (void *ctx, const unsigned char *data)
 {
   GOSTR3411_CONTEXT *hd = ctx;
-  byte m[32];
+  u32 m[8];
   unsigned int burn;
+  int i;
 
-  memcpy (m, data, 32);
+  for (i = 0; i < 8; i++)
+    m[i] = buf_get_le32(data + i*4);
   burn = do_hash_step (hd, hd->h, m);
   do_add (hd->sigma, m);
 
 <at>  <at>  -263,9 +281,9  <at>  <at>  gost3411_final (void *context)
 {
   GOSTR3411_CONTEXT *hd = context;
   size_t padlen = 0;
-  byte l[32];
+  u32 l[8];
   int i;
-  u32 nblocks;
+  MD_NBLOCKS_TYPE nblocks;
 
   if (hd->bctx.count > 0)
     {
 <at>  <at>  -286,15 +304,19  <at>  <at>  gost3411_final (void *context)
       nblocks --;
       l[0] = 256 - padlen * 8;
     }
+  l[0] |= nblocks << 8;
+  nblocks >>= 24;
 
   for (i = 1; i < 32 && nblocks != 0; i++)
     {
-      l[i] = nblocks % 256;
-      nblocks /= 256;
+      l[i] = nblocks;
+      nblocks >>= 24;
     }
 
   do_hash_step (hd, hd->h, l);
   do_hash_step (hd, hd->h, hd->sigma);
+  for (i = 0; i < 8; i++)
+    hd->h[i] = le_bswap32(hd->h[i]);
 }
 
 static byte *
 <at>  <at>  -302,7 +324,7  <at>  <at>  gost3411_read (void *context)
 {
   GOSTR3411_CONTEXT *hd = context;
 
-  return hd->h;
+  return hd->result;
 }
 
 static unsigned char asn[6] = /* Object ID is 1.2.643.2.2.3 */

commit 7aeba6c449169926076df83b01ddbfa6b41fe411
Author: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>
Date:   Fri Jun 6 22:48:35 2014 +0400

    gost28147: use bufhelp helpers
    
    * cipher/gost28147.c (gost_setkey, gost_encrypt_block, gost_decrypt_block):
      use buf_get_le32/buf_put_le32 helpers.
    
    --
    On my box this boosts GOST 28147-89 speed from 36 MiB/s up to 44.5 MiB/s.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>

diff --git a/cipher/gost28147.c b/cipher/gost28147.c
index 5456053..af3911e 100644
--- a/cipher/gost28147.c
+++ b/cipher/gost28147.c
 <at>  <at>  -33,6 +33,7  <at>  <at> 
 #include "types.h"
 #include "g10lib.h"
 #include "cipher.h"
+#include "bufhelp.h"
 
 #include "gost.h"
 #include "gost-sb.h"
 <at>  <at>  -51,10 +52,7  <at>  <at>  gost_setkey (void *c, const byte *key, unsigned keylen)
 
   for (i = 0; i < 8; i++)
     {
-      ctx->key[i] = (key[4 * i + 3] << 24) |
-                    (key[4 * i + 2] << 16) |
-                    (key[4 * i + 1] <<  8) |
-                    (key[4 * i + 0] <<  0);
+      ctx->key[i] = buf_get_le32(&key[4*i]);
     }
   return GPG_ERR_NO_ERROR;
 }
 <at>  <at>  -76,14 +74,8  <at>  <at>  gost_encrypt_block (void *c, byte *outbuf, const byte *inbuf)
   GOST28147_context *ctx = c;
   u32 n1, n2;
 
-  n1 =  (inbuf[0] << 0) |
-        (inbuf[1] << 8) |
-        (inbuf[2] << 16) |
-        (inbuf[3] << 24);
-  n2 =  (inbuf[4] << 0) |
-        (inbuf[5] << 8) |
-        (inbuf[6] << 16) |
-        (inbuf[7] << 24);
+  n1 = buf_get_le32 (inbuf);
+  n2 = buf_get_le32 (inbuf+4);
 
   n2 ^= gost_val (ctx, n1, 0); n1 ^= gost_val (ctx, n2, 1);
   n2 ^= gost_val (ctx, n1, 2); n1 ^= gost_val (ctx, n2, 3);
 <at>  <at>  -105,14 +97,8  <at>  <at>  gost_encrypt_block (void *c, byte *outbuf, const byte *inbuf)
   n2 ^= gost_val (ctx, n1, 3); n1 ^= gost_val (ctx, n2, 2);
   n2 ^= gost_val (ctx, n1, 1); n1 ^= gost_val (ctx, n2, 0);
 
-  outbuf[0 + 0] = (n2 >> (0 * 8)) & 0xff;
-  outbuf[1 + 0] = (n2 >> (1 * 8)) & 0xff;
-  outbuf[2 + 0] = (n2 >> (2 * 8)) & 0xff;
-  outbuf[3 + 0] = (n2 >> (3 * 8)) & 0xff;
-  outbuf[0 + 4] = (n1 >> (0 * 8)) & 0xff;
-  outbuf[1 + 4] = (n1 >> (1 * 8)) & 0xff;
-  outbuf[2 + 4] = (n1 >> (2 * 8)) & 0xff;
-  outbuf[3 + 4] = (n1 >> (3 * 8)) & 0xff;
+  buf_put_le32 (outbuf+0, n2);
+  buf_put_le32 (outbuf+4, n1);
 
   return /* burn_stack */ 4*sizeof(void*) /* func call */ +
                           3*sizeof(void*) /* stack */ +
 <at>  <at>  -136,14 +122,8  <at>  <at>  gost_decrypt_block (void *c, byte *outbuf, const byte *inbuf)
   GOST28147_context *ctx = c;
   u32 n1, n2;
 
-  n1 =  (inbuf[0] << 0) |
-        (inbuf[1] << 8) |
-        (inbuf[2] << 16) |
-        (inbuf[3] << 24);
-  n2 =  (inbuf[4] << 0) |
-        (inbuf[5] << 8) |
-        (inbuf[6] << 16) |
-        (inbuf[7] << 24);
+  n1 = buf_get_le32 (inbuf);
+  n2 = buf_get_le32 (inbuf+4);
 
   n2 ^= gost_val (ctx, n1, 0); n1 ^= gost_val (ctx, n2, 1);
   n2 ^= gost_val (ctx, n1, 2); n1 ^= gost_val (ctx, n2, 3);
 <at>  <at>  -165,14 +145,8  <at>  <at>  gost_decrypt_block (void *c, byte *outbuf, const byte *inbuf)
   n2 ^= gost_val (ctx, n1, 3); n1 ^= gost_val (ctx, n2, 2);
   n2 ^= gost_val (ctx, n1, 1); n1 ^= gost_val (ctx, n2, 0);
 
-  outbuf[0 + 0] = (n2 >> (0 * 8)) & 0xff;
-  outbuf[1 + 0] = (n2 >> (1 * 8)) & 0xff;
-  outbuf[2 + 0] = (n2 >> (2 * 8)) & 0xff;
-  outbuf[3 + 0] = (n2 >> (3 * 8)) & 0xff;
-  outbuf[0 + 4] = (n1 >> (0 * 8)) & 0xff;
-  outbuf[1 + 4] = (n1 >> (1 * 8)) & 0xff;
-  outbuf[2 + 4] = (n1 >> (2 * 8)) & 0xff;
-  outbuf[3 + 4] = (n1 >> (3 * 8)) & 0xff;
+  buf_put_le32 (outbuf+0, n2);
+  buf_put_le32 (outbuf+4, n1);
 
   return /* burn_stack */ 4*sizeof(void*) /* func call */ +
                           3*sizeof(void*) /* stack */ +

commit b78d504fa8745b8b04589acbbcf7dd5fe9279d13
Author: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>
Date:   Fri Jun 6 22:48:34 2014 +0400

    Fixup curve name in the GOST2012 test case
    
    * tests/basic.c (check_pubkey): fixup curve name in public key.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>

diff --git a/tests/basic.c b/tests/basic.c
index 875b36c..6d70cfd 100644
--- a/tests/basic.c
+++ b/tests/basic.c
 <at>  <at>  -6966,7 +6966,7  <at>  <at>  check_pubkey (void)
 
       "(public-key\n"
       " (ecc\n"
-      "  (curve GOST2001-test)\n"
+      "  (curve GOST2012-test)\n"
       "  (q #04115DC5BC96760C7B48598D8AB9E740D4C4A85A65BE33C1"
       "        815B5C320C854621DD5A515856D13314AF69BC5B924C8B"
       "        4DDFF75C45415C1D9DD9DD33612CD530EFE137C7C90CD4"

commit 7533b2ad46f42e98d9dba52e88e79c0311d2d3b7
Author: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>
Date:   Fri Jun 6 22:48:33 2014 +0400

    Update PBKDF2 tests with GOST R 34.11-94 test cases
    
    * tests/t-kdf.c (check_pbkdf2): Add MD_GOSTR3411_CP test cases.
    
    --
    TC26 (Technical Comitee for standardization "Cryptography and security
    mechanisms") published a document with test vectors for PBKDF2 used
    with GOST R 34.11-94 message digest function.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>

diff --git a/tests/t-kdf.c b/tests/t-kdf.c
index adbe6cc..8e728d5 100644
--- a/tests/t-kdf.c
+++ b/tests/t-kdf.c
 <at>  <at>  -864,6 +864,7  <at>  <at>  check_pbkdf2 (void)
     size_t plen;     /* Length of P. */
     const char *salt;
     size_t saltlen;
+    int hashalgo;
     unsigned long c; /* Iterations.  */
     int dklen;       /* Requested key length.  */
     const char *dk;  /* Derived key.  */
 <at>  <at>  -872,6 +873,7  <at>  <at>  check_pbkdf2 (void)
     {
       "password", 8,
       "salt", 4,
+      GCRY_MD_SHA1,
       1,
       20,
       "\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9"
 <at>  <at>  -880,6 +882,7  <at>  <at>  check_pbkdf2 (void)
     {
       "password", 8,
       "salt", 4,
+      GCRY_MD_SHA1,
       2,
       20,
       "\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e"
 <at>  <at>  -888,6 +891,7  <at>  <at>  check_pbkdf2 (void)
     {
       "password", 8,
       "salt", 4,
+      GCRY_MD_SHA1,
       4096,
       20,
       "\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad"
 <at>  <at>  -896,6 +900,7  <at>  <at>  check_pbkdf2 (void)
     {
       "password", 8,
       "salt", 4,
+      GCRY_MD_SHA1,
       16777216,
       20,
       "\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94"
 <at>  <at>  -905,6 +910,7  <at>  <at>  check_pbkdf2 (void)
     {
       "passwordPASSWORDpassword", 24,
       "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
+      GCRY_MD_SHA1,
       4096,
       25,
       "\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8"
 <at>  <at>  -914,6 +920,7  <at>  <at>  check_pbkdf2 (void)
     {
       "pass\0word", 9,
       "sa\0lt", 5,
+      GCRY_MD_SHA1,
       4096,
       16,
       "\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37"
 <at>  <at>  -922,15 +929,71  <at>  <at>  check_pbkdf2 (void)
     { /* empty password test, not in RFC-6070 */
       "", 0,
       "salt", 4,
+      GCRY_MD_SHA1,
       2,
       20,
       "\x13\x3a\x4c\xe8\x37\xb4\xd2\x52\x1e\xe2"
       "\xbf\x03\xe1\x1c\x71\xca\x79\x4e\x07\x97"
+    },
+    {
+      "password", 8,
+      "salt", 4,
+      GCRY_MD_GOSTR3411_CP,
+      1,
+      32,
+      "\x73\x14\xe7\xc0\x4f\xb2\xe6\x62\xc5\x43\x67\x42\x53\xf6\x8b\xd0"
+      "\xb7\x34\x45\xd0\x7f\x24\x1b\xed\x87\x28\x82\xda\x21\x66\x2d\x58"
+    },
+    {
+      "password", 8,
+      "salt", 4,
+      GCRY_MD_GOSTR3411_CP,
+      2,
+      32,
+      "\x99\x0d\xfa\x2b\xd9\x65\x63\x9b\xa4\x8b\x07\xb7\x92\x77\x5d\xf7"
+      "\x9f\x2d\xb3\x4f\xef\x25\xf2\x74\x37\x88\x72\xfe\xd7\xed\x1b\xb3"
+    },
+    {
+      "password", 8,
+      "salt", 4,
+      GCRY_MD_GOSTR3411_CP,
+      4096,
+      32,
+      "\x1f\x18\x29\xa9\x4b\xdf\xf5\xbe\x10\xd0\xae\xb3\x6a\xf4\x98\xe7"
+      "\xa9\x74\x67\xf3\xb3\x11\x16\xa5\xa7\xc1\xaf\xff\x9d\xea\xda\xfe"
+    },
+    /* { -- takes too long (4-5 min) to calculate
+      "password", 8,
+      "salt", 4,
+      GCRY_MD_GOSTR3411_CP,
+      16777216,
+      32,
+      "\xa5\x7a\xe5\xa6\x08\x83\x96\xd1\x20\x85\x0c\x5c\x09\xde\x0a\x52"
+      "\x51\x00\x93\x8a\x59\xb1\xb5\xc3\xf7\x81\x09\x10\xd0\x5f\xcd\x97"
+    }, */
+    {
+      "passwordPASSWORDpassword", 24,
+      "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
+      GCRY_MD_GOSTR3411_CP,
+      4096,
+      40,
+      "\x78\x83\x58\xc6\x9c\xb2\xdb\xe2\x51\xa7\xbb\x17\xd5\xf4\x24\x1f"
+      "\x26\x5a\x79\x2a\x35\xbe\xcd\xe8\xd5\x6f\x32\x6b\x49\xc8\x50\x47"
+      "\xb7\x63\x8a\xcb\x47\x64\xb1\xfd"
+    },
+    {
+      "pass\0word", 9,
+      "sa\0lt", 5,
+      GCRY_MD_GOSTR3411_CP,
+      4096,
+      20,
+      "\x43\xe0\x6c\x55\x90\xb0\x8c\x02\x25\x24"
+      "\x23\x73\x12\x7e\xdf\x9c\x8e\x9c\x32\x91"
     }
   };
   int tvidx;
   gpg_error_t err;
-  unsigned char outbuf[32];
+  unsigned char outbuf[40];
   int i;
 
   for (tvidx=0; tvidx < DIM(tv); tvidx++)
 <at>  <at>  -938,10 +1001,11  <at>  <at>  check_pbkdf2 (void)
       if (tv[tvidx].disabled)
         continue;
       if (verbose)
-        fprintf (stderr, "checking PBKDF2 test vector %d\n", tvidx);
+        fprintf (stderr, "checking PBKDF2 test vector %d algo %d\n", tvidx,
+                 tv[tvidx].hashalgo);
       assert (tv[tvidx].dklen <= sizeof outbuf);
       err = gcry_kdf_derive (tv[tvidx].p, tv[tvidx].plen,
-                             GCRY_KDF_PBKDF2, GCRY_MD_SHA1,
+                             GCRY_KDF_PBKDF2, tv[tvidx].hashalgo,
                              tv[tvidx].salt, tv[tvidx].saltlen,
                              tv[tvidx].c, tv[tvidx].dklen, outbuf);
       if (err)

commit 25d6af77e2336b5979ddbe8b90978fe5b61dfaf9
Author: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>
Date:   Fri Jun 6 22:48:32 2014 +0400

    Add GOST R 34.11-94 variant using id-GostR3411-94-CryptoProParamSet
    
    * src/gcrypt.h.in (GCRY_MD_GOSTR3411_CP): New.
    * src/cipher.h (_gcry_digest_spec_gost3411_cp): New.
    * cipher/gost28147.c (_gcry_gost_enc_one): Differentiate between
      CryptoPro and Test S-Boxes.
    * cipher/gostr3411-94.c (_gcry_digest_spec_gost3411_cp,
      gost3411_cp_init): New.
    * cipher/md.c (md_open): GCRY_MD_GOSTR3411_CP also uses B=32.
    
    --
    RFC4357 defines only two S-Boxes that should be used together with
    GOST R 34.11-94 - a testing one (from standard itself, for testing only)
    and CryptoPro one. Instead of adding a separate gcry_md_ctrl() function
    just to switch s-boxes, add a separate MD algorithm using CryptoPro
    S-box.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>

diff --git a/NEWS b/NEWS
index 5eacf30..214c676 100644
--- a/NEWS
+++ b/NEWS
 <at>  <at>  -28,6 +28,7  <at>  <at>  Noteworthy changes in version 1.7.0 (unreleased)
  GCRY_MD_FLAG_BUGEMU1            NEW.
  GCRYCTL_SET_SBOX                NEW.
  gcry_cipher_set_sbox            NEW macro.
+ GCRY_MD_GOSTR3411_CP            NEW.
 
 
 Noteworthy changes in version 1.6.0 (2013-12-16)
diff --git a/cipher/gost.h b/cipher/gost.h
index 3fbd9df..caaf34b 100644
--- a/cipher/gost.h
+++ b/cipher/gost.h
 <at>  <at>  -27,6 +27,6  <at>  <at>  typedef struct {
 
 /* This is a simple interface that will be used by GOST R 34.11-94 */
 extern unsigned int _gcry_gost_enc_one (GOST28147_context *c, const byte *key,
-    byte *out, byte *in);
+    byte *out, byte *in, int cryptopro);
 
 #endif
diff --git a/cipher/gost28147.c b/cipher/gost28147.c
index ae9e705..5456053 100644
--- a/cipher/gost28147.c
+++ b/cipher/gost28147.c
 <at>  <at>  -120,8 +120,12  <at>  <at>  gost_encrypt_block (void *c, byte *outbuf, const byte *inbuf)
 }
 
 unsigned int _gcry_gost_enc_one (GOST28147_context *c, const byte *key,
-    byte *out, byte *in)
+    byte *out, byte *in, int cryptopro)
 {
+  if (cryptopro)
+    c->sbox = sbox_CryptoPro_3411;
+  else
+    c->sbox = sbox_test_3411;
   gost_setkey (c, key, 32);
   return gost_encrypt_block (c, out, in) + 5 * sizeof(void *);
 }
diff --git a/cipher/gostr3411-94.c b/cipher/gostr3411-94.c
index 73d570f..9d065fb 100644
--- a/cipher/gostr3411-94.c
+++ b/cipher/gostr3411-94.c
 <at>  <at>  -38,6 +38,7  <at>  <at>  typedef struct {
   byte h[32];
   byte sigma[32];
   u32 len;
+  int cryptopro;
 } GOSTR3411_CONTEXT;
 
 static unsigned int
 <at>  <at>  -58,6 +59,15  <at>  <at>  gost3411_init (void *context, unsigned int flags)
   hd->bctx.count = 0;
   hd->bctx.blocksize = 32;
   hd->bctx.bwrite = transform;
+  hd->cryptopro = 0;
+}
+
+static void
+gost3411_cp_init (void *context, unsigned int flags)
+{
+  GOSTR3411_CONTEXT *hd = context;
+  gost3411_init (context, flags);
+  hd->cryptopro = 1;
 }
 
 static void
 <at>  <at>  -153,7 +163,7  <at>  <at>  do_add (unsigned char *s, unsigned char *a)
 }
 
 static unsigned int
-do_hash_step (GOST28147_context *hd, unsigned char *h, unsigned char *m)
+do_hash_step (GOSTR3411_CONTEXT *hd, unsigned char *h, unsigned char *m)
 {
   unsigned char u[32], v[32], s[32];
   unsigned char k[32];
 <at>  <at>  -166,7 +176,7  <at>  <at>  do_hash_step (GOST28147_context *hd, unsigned char *h, unsigned char *m)
   for (i = 0; i < 4; i++) {
     do_p (k, u, v);
 
-    burn = _gcry_gost_enc_one (hd, k, s + i*8, h + i*8);
+    burn = _gcry_gost_enc_one (&hd->hd, k, s + i*8, h + i*8, hd->cryptopro);
 
     do_a (u);
     if (i == 1)
 <at>  <at>  -220,7 +230,7  <at>  <at>  transform_blk (void *ctx, const unsigned char *data)
   unsigned int burn;
 
   memcpy (m, data, 32);
-  burn = do_hash_step (&hd->hd, hd->h, m);
+  burn = do_hash_step (hd, hd->h, m);
   do_add (hd->sigma, m);
 
   return /* burn_stack */ burn + 3 * sizeof(void*) + 32 + 2 * sizeof(void*);
 <at>  <at>  -283,8 +293,8  <at>  <at>  gost3411_final (void *context)
       nblocks /= 256;
     }
 
-  do_hash_step (&hd->hd, hd->h, l);
-  do_hash_step (&hd->hd, hd->h, hd->sigma);
+  do_hash_step (hd, hd->h, l);
+  do_hash_step (hd, hd->h, hd->sigma);
 }
 
 static byte *
 <at>  <at>  -310,7 +320,14  <at>  <at>  static gcry_md_oid_spec_t oid_spec_gostr3411[] =
 gcry_md_spec_t _gcry_digest_spec_gost3411_94 =
   {
     GCRY_MD_GOSTR3411_94, {0, 0},
-    "GOSTR3411_94", asn, DIM (asn), oid_spec_gostr3411, 32,
+    "GOSTR3411_94", NULL, 0, NULL, 32,
     gost3411_init, _gcry_md_block_write, gost3411_final, gost3411_read,
     sizeof (GOSTR3411_CONTEXT)
   };
+gcry_md_spec_t _gcry_digest_spec_gost3411_cp =
+  {
+    GCRY_MD_GOSTR3411_CP, {0, 0},
+    "GOSTR3411_CP", asn, DIM (asn), oid_spec_gostr3411, 32,
+    gost3411_cp_init, _gcry_md_block_write, gost3411_final, gost3411_read,
+    sizeof (GOSTR3411_CONTEXT)
+  };
diff --git a/cipher/md.c b/cipher/md.c
index 5ab89cb..a1e5859 100644
--- a/cipher/md.c
+++ b/cipher/md.c
 <at>  <at>  -53,6 +53,7  <at>  <at>  static gcry_md_spec_t *digest_list[] =
 #endif
 #ifdef USE_GOST_R_3411_94
      &_gcry_digest_spec_gost3411_94,
+     &_gcry_digest_spec_gost3411_cp,
 #endif
 #ifdef USE_GOST_R_3411_12
      &_gcry_digest_spec_stribog_256,
 <at>  <at>  -335,6 +336,7  <at>  <at>  md_open (gcry_md_hd_t *h, int algo, unsigned int flags)
                 ctx->macpads_Bsize = 128;
                 break;
               case GCRY_MD_GOSTR3411_94:
+              case GCRY_MD_GOSTR3411_CP:
                 ctx->macpads_Bsize = 32;
                 break;
               default:
diff --git a/src/cipher.h b/src/cipher.h
index ed57d3c..f4f6cc4 100644
--- a/src/cipher.h
+++ b/src/cipher.h
 <at>  <at>  -258,6 +258,7  <at>  <at>  extern gcry_md_spec_t _gcry_digest_spec_crc32;
 extern gcry_md_spec_t _gcry_digest_spec_crc32_rfc1510;
 extern gcry_md_spec_t _gcry_digest_spec_crc24_rfc2440;
 extern gcry_md_spec_t _gcry_digest_spec_gost3411_94;
+extern gcry_md_spec_t _gcry_digest_spec_gost3411_cp;
 extern gcry_md_spec_t _gcry_digest_spec_stribog_256;
 extern gcry_md_spec_t _gcry_digest_spec_stribog_512;
 extern gcry_md_spec_t _gcry_digest_spec_md2;
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 95d324b..a5f8350 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
 <at>  <at>  -1152,7 +1152,8  <at>  <at>  enum gcry_md_algos
     GCRY_MD_TIGER2        = 307, /* TIGER2 variant.   */
     GCRY_MD_GOSTR3411_94  = 308, /* GOST R 34.11-94.  */
     GCRY_MD_STRIBOG256    = 309, /* GOST R 34.11-2012, 256 bit.  */
-    GCRY_MD_STRIBOG512    = 310  /* GOST R 34.11-2012, 512 bit.  */
+    GCRY_MD_STRIBOG512    = 310, /* GOST R 34.11-2012, 512 bit.  */
+    GCRY_MD_GOSTR3411_CP  = 311  /* GOST R 34.11-94 with CryptoPro-A S-Box.  */
   };
 
 /* Flags used with the open function.  */

commit 5ee35a04362c94e680ef3633fa83b72e0aee8626
Author: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>
Date:   Fri Jun 6 22:48:31 2014 +0400

    gost28147: support GCRYCTL_SET_SBOX
    
    cipher/gost28147.c (gost_set_extra_info, gost_set_sbox): New.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>

diff --git a/cipher/gost28147.c b/cipher/gost28147.c
index 1720f45..ae9e705 100644
--- a/cipher/gost28147.c
+++ b/cipher/gost28147.c
 <at>  <at>  -175,6 +175,44  <at>  <at>  gost_decrypt_block (void *c, byte *outbuf, const byte *inbuf)
                           4*sizeof(void*) /* gost_val call */;
 }
 
+static gpg_err_code_t
+gost_set_sbox (GOST28147_context *ctx, const char *oid)
+{
+  int i;
+
+  for (i = 0; gost_oid_map[i].oid; i++)
+    {
+      if (!strcmp(gost_oid_map[i].oid, oid))
+        {
+          ctx->sbox = gost_oid_map[i].sbox;
+          return 0;
+        }
+    }
+  return GPG_ERR_VALUE_NOT_FOUND;
+}
+
+static gpg_err_code_t
+gost_set_extra_info (void *c, int what, const void *buffer, size_t buflen)
+{
+  GOST28147_context *ctx = c;
+  gpg_err_code_t ec = 0;
+
+  (void)buffer;
+  (void)buflen;
+
+  switch (what)
+    {
+    case GCRYCTL_SET_SBOX:
+      ec = gost_set_sbox (ctx, buffer);
+      break;
+
+    default:
+      ec = GPG_ERR_INV_OP;
+      break;
+    }
+  return ec;
+}
+
 static gcry_cipher_oid_spec_t oids_gost28147[] =
   {
     /* { "1.2.643.2.2.31.0", GCRY_CIPHER_MODE_CNTGOST }, */
 <at>  <at>  -193,4 +231,5  <at>  <at>  gcry_cipher_spec_t _gcry_cipher_spec_gost28147 =
     gost_setkey,
     gost_encrypt_block,
     gost_decrypt_block,
+    NULL, NULL, NULL, gost_set_extra_info,
   };

commit fb074d113fcbf66a5c20592625cb19051f3430f5
Author: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>
Date:   Fri Jun 6 22:48:30 2014 +0400

    Support setting s-box for the ciphers that require it
    
    * src/gcrypt.h.in (GCRYCTL_SET_SBOX, gcry_cipher_set_sbox): New.
    * cipher/cipher.c (_gcry_cipher_ctl): pass GCRYCTL_SET_SBOX to
      set_extra_info callback.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>

diff --git a/NEWS b/NEWS
index e1bb772..5eacf30 100644
--- a/NEWS
+++ b/NEWS
 <at>  <at>  -26,6 +26,8  <at>  <at>  Noteworthy changes in version 1.7.0 (unreleased)
  gcry_mac_get_algo               NEW.
  GCRY_MAC_HMAC_MD2               NEW.
  GCRY_MD_FLAG_BUGEMU1            NEW.
+ GCRYCTL_SET_SBOX                NEW.
+ gcry_cipher_set_sbox            NEW macro.
 
 
 Noteworthy changes in version 1.6.0 (2013-12-16)
diff --git a/cipher/cipher.c b/cipher/cipher.c
index da59061..5c44c0d 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
 <at>  <at>  -1264,6 +1264,13  <at>  <at>  _gcry_cipher_ctl (gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen)
         }
       break;
 
+    case GCRYCTL_SET_SBOX:
+      if (h->spec->set_extra_info)
+        rc = h->spec->set_extra_info
+          (&h->context.c, GCRYCTL_SET_SBOX, buffer, buflen);
+      else
+        rc = GPG_ERR_NOT_SUPPORTED;
+
     default:
       rc = GPG_ERR_INV_OP;
     }
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index bd38a24..95d324b 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
 <at>  <at>  -329,7 +329,8  <at>  <at>  enum gcry_ctl_cmds
     GCRYCTL_SET_CCM_LENGTHS = 69,
     GCRYCTL_CLOSE_RANDOM_DEVICE = 70,
     GCRYCTL_INACTIVATE_FIPS_FLAG = 71,
-    GCRYCTL_REACTIVATE_FIPS_FLAG = 72
+    GCRYCTL_REACTIVATE_FIPS_FLAG = 72,
+    GCRYCTL_SET_SBOX = 73
   };
 
 /* Perform various operations defined by CMD. */
 <at>  <at>  -1002,6 +1003,9  <at>  <at>  gcry_error_t gcry_cipher_checktag (gcry_cipher_hd_t hd, const void *intag,
 #define gcry_cipher_cts(h,on)  gcry_cipher_ctl( (h), GCRYCTL_SET_CBC_CTS, \
                                                                    NULL, on )
 
+#define gcry_cipher_set_sbox(h,oid) gcry_cipher_ctl( (h), GCRYCTL_SET_SBOX, \
+                                                     (oid), 0);
+
 /* Set counter for CTR mode.  (CTR,CTRLEN) must denote a buffer of
    block size length, or (NULL,0) to set the CTR to the all-zero block. */
 gpg_error_t gcry_cipher_setctr (gcry_cipher_hd_t hd,

commit 164738a0292b3f32c7747099ad9cadace58e5eda
Author: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>
Date:   Fri Jun 6 22:48:29 2014 +0400

    cipher/gost28147: generate optimized s-boxes from compact ones
    
    * cipher/gost-s-box.c: New. Outputs optimized expanded representation of
      s-boxes (4x256) from compact 16x8 representation.
    * cipher/Makefile.am: Add gost-sb.h dependency to gost28147.lo
    * cipher/gost.h: Add sbox to the GOST28147_context structure.
    * cipher/gost28147.c (gost_setkey): Set default s-box to test s-box from
      GOST R 34.11 (this was the only one S-box before).
    * cipher/gost28147.c (gost_val): Use sbox from the context.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>

diff --git a/.gitignore b/.gitignore
index 8b235f9..3929e4d 100644
--- a/.gitignore
+++ b/.gitignore
 <at>  <at>  -15,6 +15,8  <at>  <at>  po/messages.mo
 /stamp-h1
 /Makefile.in
 cipher/Makefile.in
+cipher/gost-s-box
+cipher/gost-sb.h
 compat/Makefile.in
 doc/Makefile.in
 m4/Makefile.in
diff --git a/cipher/Makefile.am b/cipher/Makefile.am
index 8a3bd19..c165356 100644
--- a/cipher/Makefile.am
+++ b/cipher/Makefile.am
 <at>  <at>  -93,6 +93,11  <at>  <at>  rfc2268.c \
 camellia.c camellia.h camellia-glue.c camellia-aesni-avx-amd64.S \
   camellia-aesni-avx2-amd64.S camellia-arm.S
 
+noinst_PROGRAMS = gost-s-box
+gost28147.lo: gost-sb.h
+gost-sb.h: gost-s-box
+	$(builddir)/gost-s-box $ <at> 
+
 if ENABLE_O_FLAG_MUNGING
 o_flag_munging = sed -e 's/-O\([2-9s][2-9s]*\)/-O1/' -e 's/-Ofast/-O1/g'
 else
diff --git a/cipher/gost-s-box.c b/cipher/gost-s-box.c
new file mode 100644
index 0000000..0094f65
--- /dev/null
+++ b/cipher/gost-s-box.c
 <at>  <at>  -0,0 +1,256  <at>  <at> 
+/* gost-s-box.c - GOST 28147-89 S-Box expander
+ * Copyright (C) 2013 Dmitry Eremin-Solenikov
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define DIM(v) (sizeof(v)/sizeof((v)[0]))
+
+struct gost_sbox
+{
+  const char *name;
+  const char *oid;
+  unsigned char sbox[16*8];
+} gost_sboxes[] = {
+  { "test_3411", "1.2.643.2.2.30.0", {
+      0x4, 0xE, 0x5, 0x7, 0x6, 0x4, 0xD, 0x1,
+      0xA, 0xB, 0x8, 0xD, 0xC, 0xB, 0xB, 0xF,
+      0x9, 0x4, 0x1, 0xA, 0x7, 0xA, 0x4, 0xD,
+      0x2, 0xC, 0xD, 0x1, 0x1, 0x0, 0x1, 0x0,
+
+      0xD, 0x6, 0xA, 0x0, 0x5, 0x7, 0x3, 0x5,
+      0x8, 0xD, 0x3, 0x8, 0xF, 0x2, 0xF, 0x7,
+      0x0, 0xF, 0x4, 0x9, 0xD, 0x1, 0x5, 0xA,
+      0xE, 0xA, 0x2, 0xF, 0x8, 0xD, 0x9, 0x4,
+
+      0x6, 0x2, 0xE, 0xE, 0x4, 0x3, 0x0, 0x9,
+      0xB, 0x3, 0xF, 0x4, 0xA, 0x6, 0xA, 0x2,
+      0x1, 0x8, 0xC, 0x6, 0x9, 0x8, 0xE, 0x3,
+      0xC, 0x1, 0x7, 0xC, 0xE, 0x5, 0x7, 0xE,
+
+      0x7, 0x0, 0x6, 0xB, 0x0, 0x9, 0x6, 0x6,
+      0xF, 0x7, 0x0, 0x2, 0x3, 0xC, 0x8, 0xB,
+      0x5, 0x5, 0x9, 0x5, 0xB, 0xF, 0x2, 0x8,
+      0x3, 0x9, 0xB, 0x3, 0x2, 0xE, 0xC, 0xC,
+    }
+  },
+  { "CryptoPro_3411", "1.2.643.2.2.30.1", {
+      0xA, 0x5, 0x7, 0x4, 0x7, 0x7, 0xD, 0x1,
+      0x4, 0xF, 0xF, 0xA, 0x6, 0x6, 0xE, 0x3,
+      0x5, 0x4, 0xC, 0x7, 0x4, 0x2, 0x4, 0xA,
+      0x6, 0x0, 0xE, 0xC, 0xB, 0x4, 0x1, 0x9,
+
+      0x8, 0x2, 0x9, 0x0, 0x9, 0xD, 0x7, 0x5,
+      0x1, 0xD, 0x4, 0xF, 0xC, 0x9, 0x0, 0xB,
+      0x3, 0xB, 0x1, 0x2, 0x2, 0xF, 0x5, 0x4,
+      0x7, 0x9, 0x0, 0x8, 0xA, 0x0, 0xA, 0xF,
+
+      0xD, 0x1, 0x3, 0xE, 0x1, 0xA, 0x3, 0x8,
+      0xC, 0x7, 0xB, 0x1, 0x8, 0x1, 0xC, 0x6,
+      0xE, 0x6, 0x5, 0x6, 0x0, 0x5, 0x8, 0x7,
+      0x0, 0x3, 0x2, 0x5, 0xE, 0xB, 0xF, 0xE,
+
+      0x9, 0xC, 0x6, 0xD, 0xF, 0x8, 0x6, 0xD,
+      0x2, 0xE, 0xA, 0xB, 0xD, 0xE, 0x2, 0x0,
+      0xB, 0xA, 0x8, 0x9, 0x3, 0xC, 0x9, 0x2,
+      0xF, 0x8, 0xD, 0x3, 0x5, 0x3, 0xB, 0xC,
+    }
+  },
+  { "Test_89", "1.2.643.2.2.31.0", {
+      0x4, 0xC, 0xD, 0xE, 0x3, 0x8, 0x9, 0xC,
+      0x2, 0x9, 0x8, 0x9, 0xE, 0xF, 0xB, 0x6,
+      0xF, 0xF, 0xE, 0xB, 0x5, 0x6, 0xC, 0x5,
+      0x5, 0xE, 0xC, 0x2, 0x9, 0xB, 0x0, 0x2,
+
+      0x9, 0x8, 0x7, 0x5, 0x6, 0x1, 0x3, 0xB,
+      0x1, 0x1, 0x3, 0xF, 0x8, 0x9, 0x6, 0x0,
+      0x0, 0x3, 0x9, 0x7, 0x0, 0xC, 0x7, 0x9,
+      0x8, 0xA, 0xA, 0x1, 0xD, 0x5, 0x5, 0xD,
+
+      0xE, 0x2, 0x1, 0x0, 0xA, 0xD, 0x4, 0x3,
+      0x3, 0x7, 0x5, 0xD, 0xB, 0x3, 0x8, 0xE,
+      0xB, 0x4, 0x2, 0xC, 0x7, 0x7, 0xE, 0x7,
+      0xC, 0xD, 0x4, 0x6, 0xC, 0xA, 0xF, 0xA,
+
+      0xD, 0x6, 0x6, 0xA, 0x2, 0x0, 0x1, 0xF,
+      0x7, 0x0, 0xF, 0x4, 0x1, 0xE, 0xA, 0x4,
+      0xA, 0xB, 0x0, 0x3, 0xF, 0x2, 0x2, 0x1,
+      0x6, 0x5, 0xB, 0x8, 0x4, 0x4, 0xD, 0x8,
+    }
+  },
+  { "CryptoPro_A", "1.2.643.2.2.31.1", {
+      0x9, 0x3, 0xE, 0xE, 0xB, 0x3, 0x1, 0xB,
+      0x6, 0x7, 0x4, 0x7, 0x5, 0xA, 0xD, 0xA,
+      0x3, 0xE, 0x6, 0xA, 0x1, 0xD, 0x2, 0xF,
+      0x2, 0x9, 0x2, 0xC, 0x9, 0xC, 0x9, 0x5,
+
+      0x8, 0x8, 0xB, 0xD, 0x8, 0x1, 0x7, 0x0,
+      0xB, 0xA, 0x3, 0x1, 0xD, 0x2, 0xA, 0xC,
+      0x1, 0xF, 0xD, 0x3, 0xF, 0x0, 0x6, 0xE,
+      0x7, 0x0, 0x8, 0x9, 0x0, 0xB, 0x0, 0x8,
+
+      0xA, 0x5, 0xC, 0x0, 0xE, 0x7, 0x8, 0x6,
+      0x4, 0x2, 0xF, 0x2, 0x4, 0x5, 0xC, 0x2,
+      0xE, 0x6, 0x5, 0xB, 0x2, 0x9, 0x4, 0x3,
+      0xF, 0xC, 0xA, 0x4, 0x3, 0x4, 0x5, 0x9,
+
+      0xC, 0xB, 0x0, 0xF, 0xC, 0x8, 0xF, 0x1,
+      0x0, 0x4, 0x7, 0x8, 0x7, 0xF, 0x3, 0x7,
+      0xD, 0xD, 0x1, 0x5, 0xA, 0xE, 0xB, 0xD,
+      0x5, 0x1, 0x9, 0x6, 0x6, 0x6, 0xE, 0x4,
+    }
+  },
+  { "CryptoPro_B", "1.2.643.2.2.31.2", {
+      0x8, 0x0, 0xE, 0x7, 0x2, 0x8, 0x5, 0x0,
+      0x4, 0x1, 0xC, 0x5, 0x7, 0x3, 0x2, 0x4,
+      0xB, 0x2, 0x0, 0x0, 0xC, 0x2, 0xA, 0xB,
+      0x1, 0xA, 0xA, 0xD, 0xF, 0x6, 0xB, 0xE,
+
+      0x3, 0x4, 0x9, 0xB, 0x9, 0x4, 0x9, 0x8,
+      0x5, 0xD, 0x2, 0x6, 0x5, 0xD, 0x1, 0x3,
+      0x0, 0x5, 0xD, 0x1, 0xA, 0xE, 0xC, 0x7,
+      0x9, 0xC, 0xB, 0x2, 0xB, 0xB, 0x3, 0x1,
+
+      0x2, 0x9, 0x7, 0x3, 0x1, 0xC, 0x7, 0xA,
+      0xE, 0x7, 0x5, 0xA, 0x4, 0x1, 0x4, 0x2,
+      0xA, 0x3, 0x8, 0xC, 0x0, 0x7, 0xD, 0x9,
+      0xC, 0xF, 0xF, 0xF, 0xD, 0xF, 0x0, 0x6,
+
+      0x6, 0x8, 0x6, 0xE, 0x8, 0x0, 0xF, 0xD,
+      0x7, 0x6, 0x1, 0x9, 0xE, 0x9, 0x8, 0x5,
+      0xF, 0xE, 0x4, 0x8, 0x3, 0x5, 0xE, 0xC,
+    }
+  },
+  { "CryptoPro_C", "1.2.643.2.2.31.3", {
+      0x1, 0x0, 0x8, 0x3, 0x8, 0xC, 0xA, 0x7,
+      0xB, 0x1, 0x2, 0x6, 0xD, 0x9, 0x9, 0x4,
+      0xC, 0x7, 0x5, 0x0, 0xB, 0xB, 0x6, 0x0,
+      0x2, 0xD, 0x0, 0x1, 0x0, 0x1, 0x8, 0x5,
+
+      0x9, 0xB, 0x4, 0x5, 0x4, 0x8, 0xD, 0xA,
+      0xD, 0x4, 0x9, 0xD, 0x5, 0xE, 0xE, 0x2,
+      0x0, 0x5, 0xF, 0xA, 0x1, 0x2, 0x2, 0xF,
+      0xF, 0x2, 0xA, 0x8, 0x2, 0x4, 0x0, 0xE,
+
+      0x4, 0x8, 0x3, 0xB, 0x9, 0x7, 0xF, 0xC,
+      0x5, 0xE, 0x7, 0x2, 0x3, 0x3, 0x3, 0x6,
+      0x8, 0xF, 0xC, 0x9, 0xC, 0x6, 0x5, 0x1,
+      0xE, 0xC, 0xD, 0x7, 0xE, 0x5, 0xB, 0xB,
+
+      0xA, 0x9, 0x6, 0xE, 0x6, 0xA, 0x4, 0xD,
+      0x7, 0xA, 0xE, 0xF, 0xF, 0x0, 0x1, 0x9,
+      0x6, 0x6, 0x1, 0xC, 0xA, 0xF, 0xC, 0x3,
+      0x3, 0x3, 0xB, 0x4, 0x7, 0xD, 0x7, 0x8,
+    }
+  },
+  { "CryptoPro_D", "1.2.643.2.2.31.4", {
+      0xF, 0xB, 0x1, 0x1, 0x0, 0x8, 0x3, 0x1,
+      0xC, 0x6, 0xC, 0x5, 0xC, 0x0, 0x0, 0xA,
+      0x2, 0x3, 0xB, 0xE, 0x8, 0xF, 0x6, 0x6,
+      0xA, 0x4, 0x0, 0xC, 0x9, 0x3, 0xF, 0x8,
+
+      0x6, 0xC, 0xF, 0xA, 0xD, 0x2, 0x1, 0xF,
+      0x4, 0xF, 0xE, 0x7, 0x2, 0x5, 0xE, 0xB,
+      0x5, 0xE, 0x6, 0x0, 0xA, 0xE, 0x9, 0x0,
+      0x0, 0x2, 0x5, 0xD, 0xB, 0xB, 0x2, 0x4,
+
+      0x7, 0x7, 0xA, 0x6, 0x7, 0x1, 0xD, 0xC,
+      0x9, 0xD, 0xD, 0x2, 0x3, 0xA, 0x8, 0x3,
+      0xE, 0x8, 0x4, 0xB, 0x6, 0x4, 0xC, 0x5,
+      0xD, 0x0, 0x8, 0x4, 0x5, 0x7, 0x4, 0x9,
+
+      0x1, 0x5, 0x9, 0x9, 0x4, 0xC, 0xB, 0x7,
+      0xB, 0xA, 0x3, 0x3, 0xE, 0x9, 0xA, 0xD,
+      0x8, 0x9, 0x7, 0xF, 0xF, 0xD, 0x5, 0x2,
+      0x3, 0x1, 0x2, 0x8, 0x1, 0x6, 0x7, 0xE,
+    }
+  },
+  { "TC26_A", "1.2.643.7.1.2.5.1.1", {
+      0xc, 0x6, 0xb, 0xc, 0x7, 0x5, 0x8, 0x1,
+      0x4, 0x8, 0x3, 0x8, 0xf, 0xd, 0xe, 0x7,
+      0x6, 0x2, 0x5, 0x2, 0x5, 0xf, 0x2, 0xe,
+      0x2, 0x3, 0x8, 0x1, 0xa, 0x6, 0x5, 0xd,
+
+      0xa, 0x9, 0x2, 0xd, 0x8, 0x9, 0x6, 0x0,
+      0x5, 0xa, 0xf, 0x4, 0x1, 0x2, 0x9, 0x5,
+      0xb, 0x5, 0xa, 0xf, 0x6, 0xc, 0x1, 0x8,
+      0x9, 0xc, 0xd, 0x6, 0xd, 0xa, 0xc, 0x3,
+
+      0xe, 0x1, 0xe, 0x7, 0x0, 0xb, 0xf, 0x4,
+      0x8, 0xe, 0x1, 0x0, 0x9, 0x7, 0x4, 0xf,
+      0xd, 0x4, 0x7, 0xa, 0x3, 0x8, 0xb, 0xa,
+      0x7, 0x7, 0x4, 0x5, 0xe, 0x1, 0x0, 0x6,
+
+      0x0, 0xb, 0xc, 0x3, 0xb, 0x4, 0xd, 0x9,
+      0x3, 0xd, 0x9, 0xe, 0x4, 0x3, 0xa, 0xc,
+      0xf, 0x0, 0x6, 0x9, 0x2, 0xe, 0x3, 0xb,
+      0x1, 0xf, 0x0, 0xb, 0xc, 0x0, 0x7, 0x2,
+    }
+  },
+};
+
+int main(int argc, char **argv)
+{
+  unsigned int i, j, s;
+  FILE *f;
+
+  if (argc == 1)
+    f = stdin;
+  else
+    f = fopen(argv[1], "w");
+
+  if (!f)
+    {
+      perror("fopen");
+      exit(1);
+    }
+
+  for (s = 0; s < DIM(gost_sboxes); s++)
+    {
+      unsigned char *sbox = gost_sboxes[s].sbox;
+      fprintf (f, "static const u32 sbox_%s[4*256] =\n  {", gost_sboxes[s].name);
+      for (i = 0; i < 4; i++) {
+        fprintf (f, 	"\n    /* %d */\n   ", i);
+        for (j = 0; j < 256; j++) {
+          unsigned int val;
+          if (j % 4 == 0 && j != 0)
+            fprintf (f, "\n   ");
+          val = sbox[ (j & 0xf) * 8 + 2 * i + 0] |
+               (sbox[ (j >> 4)  * 8 + 2 * i + 1] << 4);
+          val <<= (8*i);
+          val = (val << 11) | (val >> 21);
+          fprintf (f, " 0x%08x,", val);
+        }
+      }
+      fprintf (f, "\n  };\n\n");
+    }
+
+  fprintf (f, "static struct\n{\n  const char *oid;\n  const u32 *sbox;\n} gost_oid_map[] = {\n");
+
+  for (s = 0; s < DIM(gost_sboxes); s++)
+    {
+      fprintf (f, "  { \"%s\", sbox_%s },\n", gost_sboxes[s].oid, gost_sboxes[s].name );
+    }
+
+  fprintf(f, "  { NULL, NULL }\n};\n");
+
+  fclose (f);
+
+  return 0;
+}
diff --git a/cipher/gost.h b/cipher/gost.h
index d058eb2..3fbd9df 100644
--- a/cipher/gost.h
+++ b/cipher/gost.h
 <at>  <at>  -22,6 +22,7  <at>  <at> 
 
 typedef struct {
   u32 key[8];
+  const u32 *sbox;
 } GOST28147_context;
 
 /* This is a simple interface that will be used by GOST R 34.11-94 */
diff --git a/cipher/gost28147.c b/cipher/gost28147.c
index 1e48eb0..1720f45 100644
--- a/cipher/gost28147.c
+++ b/cipher/gost28147.c
 <at>  <at>  -34,277 +34,8  <at>  <at> 
 #include "g10lib.h"
 #include "cipher.h"
 
-
-/* This is an s-box from RFC4357, named GostR3411-94-TestParamSet
- * For now it is the only s-box supported, as libgcrypt lacks mechanism
- * for passing parameters to cipher in a usefull way.
- * S-boxes was modified from 4->4 to 8->8 bits unit with precalculated
- * shift and rotation by optimisation reasons.
- */
-static const u32 test_sbox[4][256] = {
-  /* 0 */
-  { 0x00072000, 0x00075000, 0x00074800, 0x00071000,
-    0x00076800, 0x00074000, 0x00070000, 0x00077000,
-    0x00073000, 0x00075800, 0x00070800, 0x00076000,
-    0x00073800, 0x00077800, 0x00072800, 0x00071800,
-    0x0005a000, 0x0005d000, 0x0005c800, 0x00059000,
-    0x0005e800, 0x0005c000, 0x00058000, 0x0005f000,
-    0x0005b000, 0x0005d800, 0x00058800, 0x0005e000,
-    0x0005b800, 0X0005F800, 0x0005a800, 0x00059800,
-    0x00022000, 0x00025000, 0x00024800, 0x00021000,
-    0x00026800, 0x00024000, 0x00020000, 0x00027000,
-    0X00023000, 0x00025800, 0x00020800, 0x00026000,
-    0x00023800, 0x00027800, 0x00022800, 0x00021800,
-    0x00062000, 0x00065000, 0x00064800, 0x00061000,
-    0x00066800, 0x00064000, 0x00060000, 0x00067000,
-    0x00063000, 0x00065800, 0x00060800, 0x00066000,
-    0x00063800, 0x00067800, 0x00062800, 0x00061800,
-    0x00032000, 0x00035000, 0x00034800, 0x00031000,
-    0x00036800, 0x00034000, 0x00030000, 0x00037000,
-    0x00033000, 0x00035800, 0x00030800, 0x00036000,
-    0x00033800, 0x00037800, 0x00032800, 0x00031800,
-    0x0006a000, 0x0006d000, 0x0006c800, 0x00069000,
-    0x0006e800, 0x0006c000, 0x00068000, 0x0006f000,
-    0x0006b000, 0x0006d800, 0x00068800, 0x0006e000,
-    0x0006b800, 0x0006f800, 0x0006a800, 0x00069800,
-    0x0007a000, 0x0007d000, 0x0007c800, 0x00079000,
-    0x0007e800, 0x0007c000, 0x00078000, 0x0007f000,
-    0x0007b000, 0x0007d800, 0x00078800, 0x0007e000,
-    0x0007b800, 0x0007f800, 0x0007a800, 0x00079800,
-    0x00052000, 0x00055000, 0x00054800, 0x00051000,
-    0x00056800, 0x00054000, 0x00050000, 0x00057000,
-    0x00053000, 0x00055800, 0x00050800, 0x00056000,
-    0x00053800, 0x00057800, 0x00052800, 0x00051800,
-    0x00012000, 0x00015000, 0x00014800, 0x00011000,
-    0x00016800, 0x00014000, 0x00010000, 0x00017000,
-    0x00013000, 0x00015800, 0x00010800, 0x00016000,
-    0x00013800, 0x00017800, 0x00012800, 0x00011800,
-    0x0001a000, 0x0001d000, 0x0001c800, 0x00019000,
-    0x0001e800, 0x0001c000, 0x00018000, 0x0001f000,
-    0x0001b000, 0x0001d800, 0x00018800, 0x0001e000,
-    0x0001b800, 0x0001f800, 0x0001a800, 0x00019800,
-    0x00042000, 0x00045000, 0x00044800, 0x00041000,
-    0x00046800, 0x00044000, 0x00040000, 0x00047000,
-    0x00043000, 0x00045800, 0x00040800, 0x00046000,
-    0x00043800, 0x00047800, 0x00042800, 0x00041800,
-    0x0000a000, 0x0000d000, 0x0000c800, 0x00009000,
-    0x0000e800, 0x0000c000, 0x00008000, 0x0000f000,
-    0x0000b000, 0x0000d800, 0x00008800, 0x0000e000,
-    0x0000b800, 0x0000f800, 0x0000a800, 0x00009800,
-    0x00002000, 0x00005000, 0x00004800, 0x00001000,
-    0x00006800, 0x00004000, 0x00000000, 0x00007000,
-    0x00003000, 0x00005800, 0x00000800, 0x00006000,
-    0x00003800, 0x00007800, 0x00002800, 0x00001800,
-    0x0003a000, 0x0003d000, 0x0003c800, 0x00039000,
-    0x0003e800, 0x0003c000, 0x00038000, 0x0003f000,
-    0x0003b000, 0x0003d800, 0x00038800, 0x0003e000,
-    0x0003b800, 0x0003f800, 0x0003a800, 0x00039800,
-    0x0002a000, 0x0002d000, 0x0002c800, 0x00029000,
-    0x0002e800, 0x0002c000, 0x00028000, 0x0002f000,
-    0x0002b000, 0x0002d800, 0x00028800, 0x0002e000,
-    0x0002b800, 0x0002f800, 0x0002a800, 0x00029800,
-    0x0004a000, 0x0004d000, 0x0004c800, 0x00049000,
-    0x0004e800, 0x0004c000, 0x00048000, 0x0004f000,
-    0x0004b000, 0x0004d800, 0x00048800, 0x0004e000,
-    0x0004b800, 0x0004f800, 0x0004a800, 0x00049800 },
-  /* 1 */
-  { 0x03a80000, 0x03c00000, 0x03880000, 0x03e80000,
-    0x03d00000, 0x03980000, 0x03a00000, 0x03900000,
-    0x03f00000, 0x03f80000, 0x03e00000, 0x03b80000,
-    0x03b00000, 0x03800000, 0x03c80000, 0x03d80000,
-    0x06a80000, 0x06c00000, 0x06880000, 0x06e80000,
-    0x06d00000, 0x06980000, 0x06a00000, 0x06900000,
-    0x06f00000, 0x06f80000, 0x06e00000, 0x06b80000,
-    0x06b00000, 0x06800000, 0x06c80000, 0x06d80000,
-    0x05280000, 0x05400000, 0x05080000, 0x05680000,
-    0x05500000, 0x05180000, 0x05200000, 0x05100000,
-    0x05700000, 0x05780000, 0x05600000, 0x05380000,
-    0x05300000, 0x05000000, 0x05480000, 0x05580000,
-    0x00a80000, 0x00c00000, 0x00880000, 0x00e80000,
-    0x00d00000, 0x00980000, 0x00a00000, 0x00900000,
-    0x00f00000, 0x00f80000, 0x00e00000, 0x00b80000,
-    0x00b00000, 0x00800000, 0x00c80000, 0x00d80000,
-    0x00280000, 0x00400000, 0x00080000, 0x00680000,
-    0x00500000, 0x00180000, 0x00200000, 0x00100000,
-    0x00700000, 0x00780000, 0x00600000, 0x00380000,
-    0x00300000, 0x00000000, 0x00480000, 0x00580000,
-    0x04280000, 0x04400000, 0x04080000, 0x04680000,
-    0x04500000, 0x04180000, 0x04200000, 0x04100000,
-    0x04700000, 0x04780000, 0x04600000, 0x04380000,
-    0x04300000, 0x04000000, 0x04480000, 0x04580000,
-    0x04a80000, 0x04c00000, 0x04880000, 0x04e80000,
-    0x04d00000, 0x04980000, 0x04a00000, 0x04900000,
-    0x04f00000, 0x04f80000, 0x04e00000, 0x04b80000,
-    0x04b00000, 0x04800000, 0x04c80000, 0x04d80000,
-    0x07a80000, 0x07c00000, 0x07880000, 0x07e80000,
-    0x07d00000, 0x07980000, 0x07a00000, 0x07900000,
-    0x07f00000, 0x07f80000, 0x07e00000, 0x07b80000,
-    0x07b00000, 0x07800000, 0x07c80000, 0x07d80000,
-    0x07280000, 0x07400000, 0x07080000, 0x07680000,
-    0x07500000, 0x07180000, 0x07200000, 0x07100000,
-    0x07700000, 0x07780000, 0x07600000, 0x07380000,
-    0x07300000, 0x07000000, 0x07480000, 0x07580000,
-    0x02280000, 0x02400000, 0x02080000, 0x02680000,
-    0x02500000, 0x02180000, 0x02200000, 0x02100000,
-    0x02700000, 0x02780000, 0x02600000, 0x02380000,
-    0x02300000, 0x02000000, 0x02480000, 0x02580000,
-    0x03280000, 0x03400000, 0x03080000, 0x03680000,
-    0x03500000, 0x03180000, 0x03200000, 0x03100000,
-    0x03700000, 0x03780000, 0x03600000, 0x03380000,
-    0x03300000, 0x03000000, 0x03480000, 0x03580000,
-    0x06280000, 0x06400000, 0x06080000, 0x06680000,
-    0x06500000, 0x06180000, 0x06200000, 0x06100000,
-    0x06700000, 0x06780000, 0x06600000, 0x06380000,
-    0x06300000, 0x06000000, 0x06480000, 0x06580000,
-    0x05a80000, 0x05c00000, 0x05880000, 0x05e80000,
-    0x05d00000, 0x05980000, 0x05a00000, 0x05900000,
-    0x05f00000, 0x05f80000, 0x05e00000, 0x05b80000,
-    0x05b00000, 0x05800000, 0x05c80000, 0x05d80000,
-    0x01280000, 0x01400000, 0x01080000, 0x01680000,
-    0x01500000, 0x01180000, 0x01200000, 0x01100000,
-    0x01700000, 0x01780000, 0x01600000, 0x01380000,
-    0x01300000, 0x01000000, 0x01480000, 0x01580000,
-    0x02a80000, 0x02c00000, 0x02880000, 0x02e80000,
-    0x02d00000, 0x02980000, 0x02a00000, 0x02900000,
-    0x02f00000, 0x02f80000, 0x02e00000, 0x02b80000,
-    0x02b00000, 0x02800000, 0x02c80000, 0x02d80000,
-    0x01a80000, 0x01c00000, 0x01880000, 0x01e80000,
-    0x01d00000, 0x01980000, 0x01a00000, 0x01900000,
-    0x01f00000, 0x01f80000, 0x01e00000, 0x01b80000,
-    0x01b00000, 0x01800000, 0x01c80000, 0x01d80000 },
-  /* 2 */
-  { 0x30000002, 0x60000002, 0x38000002, 0x08000002,
-    0x28000002, 0x78000002, 0x68000002, 0x40000002,
-    0x20000002, 0x50000002, 0x48000002, 0x70000002,
-    0x00000002, 0x18000002, 0x58000002, 0x10000002,
-    0xb0000005, 0xe0000005, 0xb8000005, 0x88000005,
-    0xa8000005, 0xf8000005, 0xe8000005, 0xc0000005,
-    0xa0000005, 0xd0000005, 0xc8000005, 0xf0000005,
-    0x80000005, 0x98000005, 0xd8000005, 0x90000005,
-    0x30000005, 0x60000005, 0x38000005, 0x08000005,
-    0x28000005, 0x78000005, 0x68000005, 0x40000005,
-    0x20000005, 0x50000005, 0x48000005, 0x70000005,
-    0x00000005, 0x18000005, 0x58000005, 0x10000005,
-    0x30000000, 0x60000000, 0x38000000, 0x08000000,
-    0x28000000, 0x78000000, 0x68000000, 0x40000000,
-    0x20000000, 0x50000000, 0x48000000, 0x70000000,
-    0x00000000, 0x18000000, 0x58000000, 0x10000000,
-    0xb0000003, 0xe0000003, 0xb8000003, 0x88000003,
-    0xa8000003, 0xf8000003, 0xe8000003, 0xc0000003,
-    0xa0000003, 0xd0000003, 0xc8000003, 0xf0000003,
-    0x80000003, 0x98000003, 0xd8000003, 0x90000003,
-    0x30000001, 0x60000001, 0x38000001, 0x08000001,
-    0x28000001, 0x78000001, 0x68000001, 0x40000001,
-    0x20000001, 0x50000001, 0x48000001, 0x70000001,
-    0x00000001, 0x18000001, 0x58000001, 0x10000001,
-    0xb0000000, 0xe0000000, 0xb8000000, 0x88000000,
-    0xa8000000, 0xf8000000, 0xe8000000, 0xc0000000,
-    0xa0000000, 0xd0000000, 0xc8000000, 0xf0000000,
-    0x80000000, 0x98000000, 0xd8000000, 0x90000000,
-    0xb0000006, 0xe0000006, 0xb8000006, 0x88000006,
-    0xa8000006, 0xf8000006, 0xe8000006, 0xc0000006,
-    0xa0000006, 0xd0000006, 0xc8000006, 0xf0000006,
-    0x80000006, 0x98000006, 0xd8000006, 0x90000006,
-    0xb0000001, 0xe0000001, 0xb8000001, 0x88000001,
-    0xa8000001, 0xf8000001, 0xe8000001, 0xc0000001,
-    0xa0000001, 0xd0000001, 0xc8000001, 0xf0000001,
-    0x80000001, 0x98000001, 0xd8000001, 0x90000001,
-    0x30000003, 0x60000003, 0x38000003, 0x08000003,
-    0x28000003, 0x78000003, 0x68000003, 0x40000003,
-    0x20000003, 0x50000003, 0x48000003, 0x70000003,
-    0x00000003, 0x18000003, 0x58000003, 0x10000003,
-    0x30000004, 0x60000004, 0x38000004, 0x08000004,
-    0x28000004, 0x78000004, 0x68000004, 0x40000004,
-    0x20000004, 0x50000004, 0x48000004, 0x70000004,
-    0x00000004, 0x18000004, 0x58000004, 0x10000004,
-    0xb0000002, 0xe0000002, 0xb8000002, 0x88000002,
-    0xa8000002, 0xf8000002, 0xe8000002, 0xc0000002,
-    0xa0000002, 0xd0000002, 0xc8000002, 0xf0000002,
-    0x80000002, 0x98000002, 0xd8000002, 0x90000002,
-    0xb0000004, 0xe0000004, 0xb8000004, 0x88000004,
-    0xa8000004, 0xf8000004, 0xe8000004, 0xc0000004,
-    0xa0000004, 0xd0000004, 0xc8000004, 0xf0000004,
-    0x80000004, 0x98000004, 0xd8000004, 0x90000004,
-    0x30000006, 0x60000006, 0x38000006, 0x08000006,
-    0x28000006, 0x78000006, 0x68000006, 0x40000006,
-    0x20000006, 0x50000006, 0x48000006, 0x70000006,
-    0x00000006, 0x18000006, 0x58000006, 0x10000006,
-    0xb0000007, 0xe0000007, 0xb8000007, 0x88000007,
-    0xa8000007, 0xf8000007, 0xe8000007, 0xc0000007,
-    0xa0000007, 0xd0000007, 0xc8000007, 0xf0000007,
-    0x80000007, 0x98000007, 0xd8000007, 0x90000007,
-    0x30000007, 0x60000007, 0x38000007, 0x08000007,
-    0x28000007, 0x78000007, 0x68000007, 0x40000007,
-    0x20000007, 0x50000007, 0x48000007, 0x70000007,
-    0x00000007, 0x18000007, 0x58000007, 0x10000007 },
-  /* 3 */
-  { 0x000000e8, 0x000000d8, 0x000000a0, 0x00000088,
-    0x00000098, 0x000000f8, 0x000000a8, 0x000000c8,
-    0x00000080, 0x000000d0, 0x000000f0, 0x000000b8,
-    0x000000b0, 0x000000c0, 0x00000090, 0x000000e0,
-    0x000007e8, 0x000007d8, 0x000007a0, 0x00000788,
-    0x00000798, 0x000007f8, 0x000007a8, 0x000007c8,
-    0x00000780, 0x000007d0, 0x000007f0, 0x000007b8,
-    0x000007b0, 0x000007c0, 0x00000790, 0x000007e0,
-    0x000006e8, 0x000006d8, 0x000006a0, 0x00000688,
-    0x00000698, 0x000006f8, 0x000006a8, 0x000006c8,
-    0x00000680, 0x000006d0, 0x000006f0, 0x000006b8,
-    0x000006b0, 0x000006c0, 0x00000690, 0x000006e0,
-    0x00000068, 0x00000058, 0x00000020, 0x00000008,
-    0x00000018, 0x00000078, 0x00000028, 0x00000048,
-    0x00000000, 0x00000050, 0x00000070, 0x00000038,
-    0x00000030, 0x00000040, 0x00000010, 0x00000060,
-    0x000002e8, 0x000002d8, 0x000002a0, 0x00000288,
-    0x00000298, 0x000002f8, 0x000002a8, 0x000002c8,
-    0x00000280, 0x000002d0, 0x000002f0, 0x000002b8,
-    0x000002b0, 0x000002c0, 0x00000290, 0x000002e0,
-    0x000003e8, 0x000003d8, 0x000003a0, 0x00000388,
-    0x00000398, 0x000003f8, 0x000003a8, 0x000003c8,
-    0x00000380, 0x000003d0, 0x000003f0, 0x000003b8,
-    0x000003b0, 0x000003c0, 0x00000390, 0x000003e0,
-    0x00000568, 0x00000558, 0x00000520, 0x00000508,
-    0x00000518, 0x00000578, 0x00000528, 0x00000548,
-    0x00000500, 0x00000550, 0x00000570, 0x00000538,
-    0x00000530, 0x00000540, 0x00000510, 0x00000560,
-    0x00000268, 0x00000258, 0x00000220, 0x00000208,
-    0x00000218, 0x00000278, 0x00000228, 0x00000248,
-    0x00000200, 0x00000250, 0x00000270, 0x00000238,
-    0x00000230, 0x00000240, 0x00000210, 0x00000260,
-    0x000004e8, 0x000004d8, 0x000004a0, 0x00000488,
-    0x00000498, 0x000004f8, 0x000004a8, 0x000004c8,
-    0x00000480, 0x000004d0, 0x000004f0, 0x000004b8,
-    0x000004b0, 0x000004c0, 0x00000490, 0x000004e0,
-    0x00000168, 0x00000158, 0x00000120, 0x00000108,
-    0x00000118, 0x00000178, 0x00000128, 0x00000148,
-    0x00000100, 0x00000150, 0x00000170, 0x00000138,
-    0x00000130, 0x00000140, 0x00000110, 0x00000160,
-    0x000001e8, 0x000001d8, 0x000001a0, 0x00000188,
-    0x00000198, 0x000001f8, 0x000001a8, 0x000001c8,
-    0x00000180, 0x000001d0, 0x000001f0, 0x000001b8,
-    0x000001b0, 0x000001c0, 0x00000190, 0x000001e0,
-    0x00000768, 0x00000758, 0x00000720, 0x00000708,
-    0x00000718, 0x00000778, 0x00000728, 0x00000748,
-    0x00000700, 0x00000750, 0x00000770, 0x00000738,
-    0x00000730, 0x00000740, 0x00000710, 0x00000760,
-    0x00000368, 0x00000358, 0x00000320, 0x00000308,
-    0x00000318, 0x00000378, 0x00000328, 0x00000348,
-    0x00000300, 0x00000350, 0x00000370, 0x00000338,
-    0x00000330, 0x00000340, 0x00000310, 0x00000360,
-    0x000005e8, 0x000005d8, 0x000005a0, 0x00000588,
-    0x00000598, 0x000005f8, 0x000005a8, 0x000005c8,
-    0x00000580, 0x000005d0, 0x000005f0, 0x000005b8,
-    0x000005b0, 0x000005c0, 0x00000590, 0x000005e0,
-    0x00000468, 0x00000458, 0x00000420, 0x00000408,
-    0x00000418, 0x00000478, 0x00000428, 0x00000448,
-    0x00000400, 0x00000450, 0x00000470, 0x00000438,
-    0x00000430, 0x00000440, 0x00000410, 0x00000460,
-    0x00000668, 0x00000658, 0x00000620, 0x00000608,
-    0x00000618, 0x00000678, 0x00000628, 0x00000648,
-    0x00000600, 0x00000650, 0x00000670, 0x00000638,
-    0x00000630, 0x00000640, 0x00000610, 0x00000660 }
-};
-
 #include "gost.h"
+#include "gost-sb.h"
 
 static gcry_err_code_t
 gost_setkey (void *c, const byte *key, unsigned keylen)
 <at>  <at>  -315,6 +46,9  <at>  <at>  gost_setkey (void *c, const byte *key, unsigned keylen)
   if (keylen != 256 / 8)
     return GPG_ERR_INV_KEYLEN;
 
+  if (!ctx->sbox)
+    ctx->sbox = sbox_test_3411;
+
   for (i = 0; i < 8; i++)
     {
       ctx->key[i] = (key[4 * i + 3] << 24) |
 <at>  <at>  -329,10 +63,10  <at>  <at>  static u32
 gost_val (GOST28147_context *ctx, u32 cm1, int subkey)
 {
   cm1 += ctx->key[subkey];
-  cm1 = test_sbox[0][ (cm1 >>  0) & 0xff] |
-        test_sbox[1][ (cm1 >>  8) & 0xff] |
-        test_sbox[2][ (cm1 >> 16) & 0xff] |
-        test_sbox[3][ (cm1 >> 24) & 0xff];
+  cm1 = ctx->sbox[0*256 + ((cm1 >>  0) & 0xff)] |
+        ctx->sbox[1*256 + ((cm1 >>  8) & 0xff)] |
+        ctx->sbox[2*256 + ((cm1 >> 16) & 0xff)] |
+        ctx->sbox[3*256 + ((cm1 >> 24) & 0xff)];
   return cm1;
 }
 

commit 34a58010000288515636706811c3837f32957b2e
Author: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>
Date:   Fri Jun 6 22:48:28 2014 +0400

    gost28147: add OIDs used to define cipher mode
    
    * cipher/gost28147 (oids_gost28147): Add OID from RFC4357.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>

diff --git a/cipher/gost28147.c b/cipher/gost28147.c
index c094209..1e48eb0 100644
--- a/cipher/gost28147.c
+++ b/cipher/gost28147.c
 <at>  <at>  -441,10 +441,20  <at>  <at>  gost_decrypt_block (void *c, byte *outbuf, const byte *inbuf)
                           4*sizeof(void*) /* gost_val call */;
 }
 
+static gcry_cipher_oid_spec_t oids_gost28147[] =
+  {
+    /* { "1.2.643.2.2.31.0", GCRY_CIPHER_MODE_CNTGOST }, */
+    { "1.2.643.2.2.31.1", GCRY_CIPHER_MODE_CFB },
+    { "1.2.643.2.2.31.2", GCRY_CIPHER_MODE_CFB },
+    { "1.2.643.2.2.31.3", GCRY_CIPHER_MODE_CFB },
+    { "1.2.643.2.2.31.4", GCRY_CIPHER_MODE_CFB },
+    { NULL }
+  };
+
 gcry_cipher_spec_t _gcry_cipher_spec_gost28147 =
   {
     GCRY_CIPHER_GOST28147, {0, 0},
-    "GOST28147", NULL, NULL, 8, 256,
+    "GOST28147", NULL, oids_gost28147, 8, 256,
     sizeof (GOST28147_context),
     gost_setkey,
     gost_encrypt_block,

commit 8b221cf5ce233c8c49a4e4ecebb70d523fc37837
Author: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>
Date:   Fri Jun 6 22:48:26 2014 +0400

    GOST R 34.11-94 add OIDs
    
    * cipher/gostr3411-94.c: Add OIDs for GOST R 34.11-94 from RFC 4357.
    
    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov <at> gmail.com>

diff --git a/cipher/gostr3411-94.c b/cipher/gostr3411-94.c
index 9a39733..73d570f 100644
--- a/cipher/gostr3411-94.c
+++ b/cipher/gostr3411-94.c
 <at>  <at>  -294,10 +294,23  <at>  <at>  gost3411_read (void *context)
 
   return hd->h;
 }
+
+static unsigned char asn[6] = /* Object ID is 1.2.643.2.2.3 */
+  { 0x2a, 0x85, 0x03, 0x02, 0x02, 0x03 };
+
+static gcry_md_oid_spec_t oid_spec_gostr3411[] =
+  {
+    /* iso.member-body.ru.rans.cryptopro.3 (gostR3411-94-with-gostR3410-2001) */
+    { "1.2.643.2.2.3" },
+    /* iso.member-body.ru.rans.cryptopro.9 (gostR3411-94) */
+    { "1.2.643.2.2.9" },
+    {NULL},
+  };
+
 gcry_md_spec_t _gcry_digest_spec_gost3411_94 =
   {
     GCRY_MD_GOSTR3411_94, {0, 0},
-    "GOSTR3411_94", NULL, 0, NULL, 32,
+    "GOSTR3411_94", asn, DIM (asn), oid_spec_gostr3411, 32,
     gost3411_init, _gcry_md_block_write, gost3411_final, gost3411_read,
     sizeof (GOSTR3411_CONTEXT)
   };

-----------------------------------------------------------------------

Summary of changes:
 .gitignore            |    2 +
 NEWS                  |    3 +
 cipher/Makefile.am    |    5 +
 cipher/cipher.c       |    7 +
 cipher/gost-s-box.c   |  256 ++++++++++++++++++++++++++++++
 cipher/gost.h         |    5 +-
 cipher/gost28147.c    |  411 +++++++++++--------------------------------------
 cipher/gostr3411-94.c |  238 +++++++++++++++++-----------
 cipher/md.c           |    2 +
 src/cipher.h          |    1 +
 src/gcrypt.h.in       |    9 +-
 tests/basic.c         |    2 +-
 tests/t-kdf.c         |   70 ++++++++-
 13 files changed, 592 insertions(+), 419 deletions(-)
 create mode 100644 cipher/gost-s-box.c


hooks/post-receive
--

-- 
The GNU crypto library
http://git.gnupg.org


_______________________________________________
Gnupg-commits mailing list
Gnupg-commits <at> gnupg.org
http://lists.gnupg.org/mailman/listinfo/gnupg-commits
NIIBE Yutaka | 19 Jun 07:58 2014

[PATCH] Curve25519 patch revised

Hello,

Here is a revised patch for Curve25519 support.  With
mpi_swap_conditional, it's getting to constant-time.

diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index 0f622f7..e7dbc17 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
 <at>  <at>  -40,7 +40,7  <at>  <at>  static const struct
   const char *other; /* Other name. */
 } curve_aliases[] =
   {
-  /*{ "Curve25519", "1.3.6.1.4.1.3029.1.5.1" },*/
+    { "Curve25519", "1.3.6.1.4.1.3029.1.5.1" },
     { "Ed25519",    "1.3.6.1.4.1.11591.15.1" },

     { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID  */
 <at>  <at>  -127,6 +127,17  <at>  <at>  static const ecc_domain_parms_t domain_parms[] =
       "0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A",
       "0x6666666666666666666666666666666666666666666666666666666666666658"
     },
+    {
+      /* (y^2 = x^3 + 486662*x^2 + x) */
+      "Curve25519", 256, 0,
+      MPI_EC_MONTGOMERY, ECC_DIALECT_STANDARD,
+      "0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED",
+      "0x01DB41",
+      "0x01",
+      "0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED",
+      "0x0000000000000000000000000000000000000000000000000000000000000009",
+      "0x20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9"
+    },
 #if 0 /* No real specs yet found.  */
     {
       /* x^2 + y^2 = 1 + 3617x^2y^2 mod 2^414 - 17 */
 <at>  <at>  -507,9 +518,8  <at>  <at>  _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
     {
     case MPI_EC_WEIERSTRASS:
     case MPI_EC_EDWARDS:
-      break;
     case MPI_EC_MONTGOMERY:
-      return GPG_ERR_NOT_SUPPORTED;
+      break;
     default:
       return GPG_ERR_BUG;
     }
diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c
index 3f284fe..595aa0c 100644
--- a/cipher/ecc-misc.c
+++ b/cipher/ecc-misc.c
 <at>  <at>  -202,8 +202,13  <at>  <at>  _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value)
     }
   if (*buf != 4)
     {
+      /* x-coordinate only */
+      mpi_set (result->x, value);
+      mpi_clear (result->y);
+      mpi_set_ui (result->z, 1);
+
       xfree (buf_memory);
-      return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression.  */
+      return 0;
     }
   if ( ((n-1)%2) )
     {
diff --git a/cipher/ecc.c b/cipher/ecc.c
index e0be2d4..6a60785 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
 <at>  <at>  -117,7 +117,25  <at>  <at>  nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
   point_init (&Q);

   /* Generate a secret.  */
-  if (ctx->dialect == ECC_DIALECT_ED25519)
+  /*
+   * FIXME.  It should be something like this:
+   *
+   *   When the co-factor of the curve is not 1, we guarantee that
+   *   scalar value k is multiple of its co-factor to avoid sub-group
+   *   attack.  Also, we make sure that the most significant bit of k
+   *   is 1.
+   *
+   * It works for now as we only have two curves which have co-factor!=1;
+   * Ed25519 and Curve25519.
+   * Note that we need some a way to get number of bits of the curve to
+   * set MSB of k.  Currently, E.nbits is not precise for this purpuse.
+   * We also need a way to get co-factor of a curve.
+   *
+   * Currently, we distinguish the two curves by ECC_DIALECT_ED25519
+   * and MPI_EC_MONTGOMERY, which works, but is not that correct.
+   */
+  if (ctx->dialect == ECC_DIALECT_ED25519
+      || E->model == MPI_EC_MONTGOMERY)
     {
       char *rndbuf;

 <at>  <at>  -156,7 +174,7  <at>  <at>  nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
    * possibilities without any loss of security.  Note that we don't
    * do that for Ed25519 so that we do not violate the special
    * construction of the secret key.  */
-  if (E->dialect == ECC_DIALECT_ED25519)
+  if (E->dialect == ECC_DIALECT_ED25519 || E->model == MPI_EC_MONTGOMERY)
     point_set (&sk->Q, &Q);
   else
     {
 <at>  <at>  -227,12 +245,8  <at>  <at>  static void
 test_keys (ECC_secret_key *sk, unsigned int nbits)
 {
   ECC_public_key pk;
-  gcry_mpi_t test = mpi_new (nbits);
+  gcry_mpi_t test;
   mpi_point_struct R_;
-  gcry_mpi_t c = mpi_new (nbits);
-  gcry_mpi_t out = mpi_new (nbits);
-  gcry_mpi_t r = mpi_new (nbits);
-  gcry_mpi_t s = mpi_new (nbits);

   if (DBG_CIPHER)
     log_debug ("Testing key.\n");
 <at>  <at>  -243,27 +257,82  <at>  <at>  test_keys (ECC_secret_key *sk, unsigned int nbits)
   point_init (&pk.Q);
   point_set (&pk.Q, &sk->Q);

-  _gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
+  if (sk->E.model == MPI_EC_MONTGOMERY)
+    /* It's ECDH only. */
+    /* FIXME: see the FIXME comment of nist_generate_key.
+     * Here, we generate ephemeral key, same handling is needed for secret.
+     */
+    {
+      char *rndbuf;
+      gcry_mpi_t x0, x1;
+      mpi_ec_t ec;
+
+      test = mpi_new (256);
+      rndbuf = _gcry_random_bytes (32, GCRY_WEAK_RANDOM);
+      rndbuf[0] &= 0x7f;  /* Clear bit 255. */
+      rndbuf[0] |= 0x40;  /* Set bit 254.   */
+      rndbuf[31] &= 0xf8; /* Clear bits 2..0 so that d mod 8 == 0  */
+      _gcry_mpi_set_buffer (test, rndbuf, 32, 0);
+      xfree (rndbuf);
+
+      ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, 0,
+                                        pk.E.p, pk.E.a, pk.E.b);
+      x0 = mpi_new (0);
+      x1 = mpi_new (0);

-  if (_gcry_ecc_ecdsa_sign (test, sk, r, s, 0, 0) )
-    log_fatal ("ECDSA operation: sign failed\n");
+      /* R_ = kQ  <=>  R_ = kdG  */
+      _gcry_mpi_ec_mul_point (&R_, test, &pk.Q, ec);
+      if (_gcry_mpi_ec_get_affine (x0, NULL, &R_, ec))
+          log_fatal ("ecdh: Failed to get affine coordinates for kQ\n");

-  if (_gcry_ecc_ecdsa_verify (test, &pk, r, s))
-    {
-      log_fatal ("ECDSA operation: sign, verify failed\n");
+      /* R_ = kG */
+      _gcry_mpi_ec_mul_point (&R_, test, &pk.E.G, ec);
+      /* R_ = dkG */
+      _gcry_mpi_ec_mul_point (&R_, sk->d, &R_, ec);
+
+      if (_gcry_mpi_ec_get_affine (x1, NULL, &R_, ec))
+        log_fatal ("ecdh: Failed to get affine coordinates for dkG\n");
+
+      if (mpi_cmp (x0, x1))
+        {
+          log_fatal ("ECDH test failed.\n");
+        }
+
+      mpi_free (x0);
+      mpi_free (x1);
+      _gcry_mpi_ec_free (ec);
     }
+  else
+    {
+      gcry_mpi_t c = mpi_new (nbits);
+      gcry_mpi_t out = mpi_new (nbits);
+      gcry_mpi_t r = mpi_new (nbits);
+      gcry_mpi_t s = mpi_new (nbits);

-  if (DBG_CIPHER)
-    log_debug ("ECDSA operation: sign, verify ok.\n");
+      test = mpi_new (nbits);
+      _gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
+
+      if (_gcry_ecc_ecdsa_sign (test, sk, r, s, 0, 0) )
+        log_fatal ("ECDSA operation: sign failed\n");
+
+      if (_gcry_ecc_ecdsa_verify (test, &pk, r, s))
+        {
+          log_fatal ("ECDSA operation: sign, verify failed\n");
+        }
+
+      if (DBG_CIPHER)
+        log_debug ("ECDSA operation: sign, verify ok.\n");
+
+      mpi_free (s);
+      mpi_free (r);
+      mpi_free (out);
+      mpi_free (c);
+    }

   point_free (&pk.Q);
   _gcry_ecc_curve_free (&pk.E);

   point_free (&R_);
-  mpi_free (s);
-  mpi_free (r);
-  mpi_free (out);
-  mpi_free (c);
   mpi_free (test);
 }

diff --git a/mpi/ec.c b/mpi/ec.c
index 4f35de0..f2dd0f0 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
 <at>  <at>  -600,10 +600,13  <at>  <at>  _gcry_mpi_ec_get_affine (gcry_mpi_t x, gcry_mpi_t y, mpi_point_t point,

     case MPI_EC_MONTGOMERY:
       {
-        log_fatal ("%s: %s not yet supported\n",
-                   "_gcry_mpi_ec_get_affine", "Montgomery");
+        if (x)
+          mpi_set (x, point->x);
+
+        if (y)
+          mpi_set (y, point->y);
       }
-      return -1;
+      return 0;

     case MPI_EC_EDWARDS:
       {
 <at>  <at>  -1073,6 +1076,35  <at>  <at>  add_points_edwards (mpi_point_t result,
 }

+/* PRD = 2 * P1.
+   SUM = P1 + P2.
+   P1 - P2 = DIF  */
+static void
+dup_and_add_montgomery (mpi_point_t prd, mpi_point_t sum,
+                        mpi_point_t p1, mpi_point_t p2, gcry_mpi_t dif_x,
+                        mpi_ec_t ctx)
+{
+  ec_addm (sum->x, p2->x, p2->z, ctx);
+  ec_subm (p2->z, p2->x, p2->z, ctx);
+  ec_addm (prd->x, p1->x, p1->z, ctx);
+  ec_subm (p1->z, p1->x, p1->z, ctx);
+  ec_mulm (p2->x, p1->z, sum->x, ctx);
+  ec_mulm (p2->z, prd->x, p2->z, ctx);
+  ec_pow2 (p1->x, prd->x, ctx);
+  ec_pow2 (p1->z, p1->z, ctx);
+  ec_addm (sum->x, p2->x, p2->z, ctx);
+  ec_subm (p2->z, p2->x, p2->z, ctx);
+  ec_mulm (prd->x, p1->x, p1->z, ctx);
+  ec_subm (p1->z, p1->x, p1->z, ctx);
+  ec_pow2 (sum->x, sum->x, ctx);
+  ec_pow2 (sum->z, p2->z, ctx);
+  ec_mulm (prd->z, p1->z, ctx->a, ctx); /* ctx->a: (A-2)/4 */
+  ec_mulm (sum->z, sum->z, dif_x, ctx);
+  ec_addm (prd->z, p1->x, prd->z, ctx);
+  ec_mulm (prd->z, prd->z, p1->z, ctx);
+}
+
+
 /* RESULT = P1 + P2 */
 void
 _gcry_mpi_ec_add_points (mpi_point_t result,
 <at>  <at>  -1144,6 +1176,79  <at>  <at>  _gcry_mpi_ec_mul_point (mpi_point_t result,
         }
       return;
     }
+  else if (ctx->model == MPI_EC_MONTGOMERY)
+    {
+      unsigned int nbits;
+      int j;
+      mpi_point_struct p1_, p2_;
+      unsigned long sw;
+
+      nbits = mpi_get_nbits (scalar);
+      point_init (&p1);
+      point_init (&p2);
+      point_init (&p1_);
+      point_init (&p2_);
+      mpi_set_ui (p1.x, 1);
+      mpi_free (p2.x);
+      p2.x  = mpi_copy (point->x);
+      mpi_set_ui (p2.z, 1);
+
+      for (j=nbits-1; j >= 0; j--)
+        {
+          mpi_point_t q1, q2;
+
+	  sw = mpi_test_bit (scalar, j);
+	  q1 = &p1;
+	  q2 = &p2;
+	  mpi_swap_conditional (q1->x, q2->x, sw);
+	  mpi_swap_conditional (q1->y, q2->y, sw);
+	  mpi_swap_conditional (q1->z, q2->z, sw);
+          dup_and_add_montgomery (&p1_, &p2_, q1, q2, point->x, ctx);
+	  mpi_swap_conditional (p1_.x, p2_.x, sw);
+	  mpi_swap_conditional (p1_.y, p2_.y, sw);
+	  mpi_swap_conditional (p1_.z, p2_.z, sw);
+
+          if (--j < 0)
+            break;
+
+	  sw = mpi_test_bit (scalar, j);
+	  q1 = &p1_;
+	  q2 = &p2_;
+	  mpi_swap_conditional (q1->x, q2->x, sw);
+	  mpi_swap_conditional (q1->y, q2->y, sw);
+	  mpi_swap_conditional (q1->z, q2->z, sw);
+          dup_and_add_montgomery (&p1, &p2, q1, q2, point->x, ctx);
+	  mpi_swap_conditional (p1.x, p2.x, sw);
+	  mpi_swap_conditional (p1.y, p2.y, sw);
+	  mpi_swap_conditional (p1.z, p2.z, sw);
+        }
+
+      z1 = mpi_new (0);
+      mpi_clear (result->y);
+      sw = (nbits & 1);
+      mpi_swap_conditional (p1.x, p1_.x, sw);
+      mpi_swap_conditional (p1.y, p1_.y, sw);
+      mpi_swap_conditional (p1.z, p1_.z, sw);
+
+      if (p1.z->nlimbs == 0)
+	{
+	  mpi_set_ui (result->x, 1);
+	  mpi_set_ui (result->z, 0);
+	}
+      else
+	{
+	  ec_invm (z1, p1.z, ctx);
+	  ec_mulm (result->x, p1.x, z1, ctx);
+	  mpi_set_ui (result->z, 1);
+	}
+
+      mpi_free (z1);
+      point_free (&p1);
+      point_free (&p2);
+      point_free (&p1_);
+      point_free (&p2_);
+      return;
+    }

   x1 = mpi_alloc_like (ctx->p);
   y1 = mpi_alloc_like (ctx->p);
 <at>  <at>  -1266,8 +1371,12  <at>  <at>  _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx)
       }
       break;
     case MPI_EC_MONTGOMERY:
+#if 0
       log_fatal ("%s: %s not yet supported\n",
                  "_gcry_mpi_ec_curve_point", "Montgomery");
+#else
+      res = 1;
+#endif
       break;
     case MPI_EC_EDWARDS:
       {
diff --git a/tests/curves.c b/tests/curves.c
index 0581452..ae699d4 100644
--- a/tests/curves.c
+++ b/tests/curves.c
 <at>  <at>  -29,7 +29,7  <at>  <at> 
 #include "../src/gcrypt-int.h"

 /* Number of curves defined in ../cipger/ecc.c */
-#define N_CURVES 21
+#define N_CURVES 22

 /* A real world sample public key.  */
 static char const sample_key_1[] =
 <at>  <at>  -64,6 +64,18  <at>  <at>  static char const sample_key_2_curve[] = "brainpoolP160r1";
 static unsigned int sample_key_2_nbits = 160;

+/* Another sample public key.  */
+static char const sample_key_3[] =
+"(public-key\n"
+" (ecdh\n"
+"  (curve Curve25519)\n"
+"  (q #040000000000000000000000000000000000000000000000000000000000000000"
+"        0000000000000000000000000000000000000000000000000000000000000000#)\n"
+"  ))";
+static char const sample_key_3_curve[] = "Curve25519";
+static unsigned int sample_key_3_nbits = 256;
+
+
 /* Program option flags.  */
 static int verbose;
 static int error_count;
 <at>  <at>  -91,6 +103,42  <at>  <at>  die (const char *format, ...)
 }

+static gcry_mpi_t
+hex2mpi (const char *string)
+{
+  gpg_error_t err;
+  gcry_mpi_t val;
+
+  err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
+  if (err)
+    die ("hex2mpi '%s' failed: %s\n", string, gpg_strerror (err));
+  return val;
+}
+
+
+/* Print an MPI S-expression.  */
+static void
+print_mpi (const char *name, gcry_mpi_t a)
+{
+  gcry_error_t err;
+  unsigned char *buf;
+  int writerr = 0;
+
+  err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buf, NULL, a);
+  if (err)
+    die ("gcry_mpi_aprint failed: %s\n", gcry_strerror (err));
+
+  printf ("  (%s #%s#)\n", name, buf);
+  if (ferror (stdout))
+    writerr++;
+  if (!writerr && fflush (stdout) == EOF)
+    writerr++;
+  if (writerr)
+    die ("writing output failed\n");
+  gcry_free (buf);
+}
+
+
 static void
 list_curves (void)
 {
 <at>  <at>  -185,6 +233,85  <at>  <at>  check_get_params (void)
 }

+static void
+check_montgomery (void)
+{
+  gpg_error_t err;
+  gcry_sexp_t key;
+  const char *name;
+  unsigned int nbits;
+
+  gcry_ctx_t ctx;
+  gcry_mpi_point_t G, Q;
+  gcry_mpi_t d;
+  gcry_mpi_t x, y, z;
+
+  err = gcry_sexp_new (&key, sample_key_3, 0, 1);
+  if (err)
+    die ("parsing s-expression string failed: %s\n", gpg_strerror (err));
+  name = gcry_pk_get_curve (key, 0, &nbits);
+  if (!name)
+    fail ("curve name not found for sample_key_3\n");
+  else if (strcmp (name, sample_key_3_curve))
+    fail ("expected curve name %s but got %s for sample_key_3\n",
+          sample_key_3_curve, name);
+  else if (nbits != sample_key_3_nbits)
+    fail ("expected curve size %u but got %u for sample_key_3\n",
+          sample_key_3_nbits, nbits);
+
+  gcry_sexp_release (key);
+
+  Q = gcry_mpi_point_new (0);
+
+  err = gcry_mpi_ec_new (&ctx, NULL, "Curve25519");
+  if (err)
+    fail ("can't create ec context: %s\n", gpg_strerror (err));
+
+#if 0
+  d = hex2mpi ("40000000000000000000000000000000"
+               "00000000000000000000000000000000");
+  G = gcry_mpi_ec_get_point ("g", ctx, 1);
+  if (!G)
+    fail ("can't get basepoint of the curve: %s\n", gpg_strerror (err));
+#else
+  d = hex2mpi ("7d74fb61db3100e11e4d4ae171daf820688f3bcfa631565272a998b8f4e8c290");
+  {
+    gcry_mpi_t gx;
+    gx = hex2mpi ("3dc16d73d4222d12eb54623c85f3fb5ebdab33c1bd5865780654f1b0ed696ddf");
+
+    G = gcry_mpi_point_new (0);
+    gcry_mpi_point_snatch_set (G, gx, NULL, NULL);
+  }
+#endif
+
+  gcry_mpi_ec_mul (Q, d, G, ctx);
+
+  x = gcry_mpi_new (0);
+  y = gcry_mpi_new (0);
+  z = gcry_mpi_new (0);
+
+  gcry_mpi_point_get (x, y, z, Q);
+
+  print_mpi ("Q.x", x);
+  print_mpi ("Q.y", y);
+  print_mpi ("Q.z", z);
+
+  if (gcry_mpi_ec_get_affine (x, NULL, Q, ctx))
+    fail ("failed to get affine coordinates\n");
+
+  print_mpi ("q.x", x);
+  /* 16B53A046DEEDD81ED6B0D470CE46DD9B5FAC6124F3D22358AA7CD2911FCFABC */
+
+  gcry_mpi_release (z);
+  gcry_mpi_release (y);
+  gcry_mpi_release (x);
+
+  gcry_mpi_point_release (Q);
+  gcry_mpi_release (d);
+  gcry_mpi_point_release (G);
+  gcry_ctx_release (ctx);
+}
+
 int
 main (int argc, char **argv)
 {
 <at>  <at>  -205,6 +332,7  <at>  <at>  main (int argc, char **argv)
   list_curves ();
   check_matching ();
   check_get_params ();
+  check_montgomery ();

   return error_count ? 1 : 0;
 }
diff --git a/tests/keygen.c b/tests/keygen.c
index 4aff9c9..c53246c 100644
--- a/tests/keygen.c
+++ b/tests/keygen.c
 <at>  <at>  -365,7 +365,7  <at>  <at>  static void
 check_ecc_keys (void)
 {
   const char *curves[] = { "NIST P-521", "NIST P-384", "NIST P-256",
-                           "Ed25519", NULL };
+                           "Ed25519", "Curve25519", NULL };
   int testno;
   gcry_sexp_t keyparm, key;
   int rc;
--

-- 

Gmane