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

by Dmitry Eremin-Solenikov cvs at cvs.gnupg.org
Sat Jun 28 10:52:54 CEST 2014


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
@@ -26,7 +26,7 @@ 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
@@ -69,13 +69,9 @@ 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);
@@ -97,23 +93,41 @@ 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
@@ -25,6 +25,7 @@
 
 #include "g10lib.h"
 #include "bithelp.h"
+#include "bufhelp.h"
 #include "cipher.h"
 #include "hash-common.h"
 
@@ -35,8 +36,11 @@
 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;
@@ -71,102 +75,122 @@ 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;
 
@@ -176,7 +200,7 @@ 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)
@@ -186,33 +210,26 @@ 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 */ +
@@ -221,15 +238,16 @@ 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);
 
@@ -263,9 +281,9 @@ 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)
     {
@@ -286,15 +304,19 @@ 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 *
@@ -302,7 +324,7 @@ 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
@@ -33,6 +33,7 @@
 #include "types.h"
 #include "g10lib.h"
 #include "cipher.h"
+#include "bufhelp.h"
 
 #include "gost.h"
 #include "gost-sb.h"
@@ -51,10 +52,7 @@ 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;
 }
@@ -76,14 +74,8 @@ 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);
@@ -105,14 +97,8 @@ 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 */ +
@@ -136,14 +122,8 @@ 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);
@@ -165,14 +145,8 @@ 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
@@ -6966,7 +6966,7 @@ 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
@@ -864,6 +864,7 @@ 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.  */
@@ -872,6 +873,7 @@ check_pbkdf2 (void)
     {
       "password", 8,
       "salt", 4,
+      GCRY_MD_SHA1,
       1,
       20,
       "\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9"
@@ -880,6 +882,7 @@ check_pbkdf2 (void)
     {
       "password", 8,
       "salt", 4,
+      GCRY_MD_SHA1,
       2,
       20,
       "\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e"
@@ -888,6 +891,7 @@ check_pbkdf2 (void)
     {
       "password", 8,
       "salt", 4,
+      GCRY_MD_SHA1,
       4096,
       20,
       "\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad"
@@ -896,6 +900,7 @@ check_pbkdf2 (void)
     {
       "password", 8,
       "salt", 4,
+      GCRY_MD_SHA1,
       16777216,
       20,
       "\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94"
@@ -905,6 +910,7 @@ check_pbkdf2 (void)
     {
       "passwordPASSWORDpassword", 24,
       "saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
+      GCRY_MD_SHA1,
       4096,
       25,
       "\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8"
@@ -914,6 +920,7 @@ check_pbkdf2 (void)
     {
       "pass\0word", 9,
       "sa\0lt", 5,
+      GCRY_MD_SHA1,
       4096,
       16,
       "\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37"
@@ -922,15 +929,71 @@ 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++)
@@ -938,10 +1001,11 @@ 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
@@ -28,6 +28,7 @@ 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
@@ -27,6 +27,6 @@ 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
@@ -120,8 +120,12 @@ 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
@@ -38,6 +38,7 @@ typedef struct {
   byte h[32];
   byte sigma[32];
   u32 len;
+  int cryptopro;
 } GOSTR3411_CONTEXT;
 
 static unsigned int
@@ -58,6 +59,15 @@ 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
@@ -153,7 +163,7 @@ 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];
@@ -166,7 +176,7 @@ 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)
@@ -220,7 +230,7 @@ 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*);
@@ -283,8 +293,8 @@ 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 *
@@ -310,7 +320,14 @@ 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
@@ -53,6 +53,7 @@ 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,
@@ -335,6 +336,7 @@ 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
@@ -258,6 +258,7 @@ 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
@@ -1152,7 +1152,8 @@ 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
@@ -175,6 +175,44 @@ 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 }, */
@@ -193,4 +231,5 @@ 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
@@ -26,6 +26,8 @@ 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
@@ -1264,6 +1264,13 @@ _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
@@ -329,7 +329,8 @@ 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. */
@@ -1002,6 +1003,9 @@ 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
@@ -15,6 +15,8 @@ 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
@@ -93,6 +93,11 @@ 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 $@
+
 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
@@ -0,0 +1,256 @@
+/* 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
@@ -22,6 +22,7 @@
 
 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
@@ -34,277 +34,8 @@
 #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)
@@ -315,6 +46,9 @@ 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) |
@@ -329,10 +63,10 @@ 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
@@ -441,10 +441,20 @@ 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
@@ -294,10 +294,23 @@ 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




More information about the Gcrypt-devel mailing list