summaryrefslogtreecommitdiff
path: root/plugins/MirOTR/Libgcrypt/cipher/gostr3411-94.c
diff options
context:
space:
mode:
authorRené Schümann <white06tiger@gmail.com>2015-03-20 12:32:29 +0000
committerRené Schümann <white06tiger@gmail.com>2015-03-20 12:32:29 +0000
commit539705d58fc39a28388ff18c695dd406f4ffd1d9 (patch)
tree51db7a37a66c09f41734ba5573d972aae9f30d71 /plugins/MirOTR/Libgcrypt/cipher/gostr3411-94.c
parent90171f125f36488dc08f5cfe0b0d4b78d995f08d (diff)
MirOTR: Libgcrypt and Libgpg-error update
Libgcrypt 1.4.6 => 1.6.3 Libgpg-error 1.9 => 1.18 git-svn-id: http://svn.miranda-ng.org/main/trunk@12449 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/MirOTR/Libgcrypt/cipher/gostr3411-94.c')
-rw-r--r--plugins/MirOTR/Libgcrypt/cipher/gostr3411-94.c286
1 files changed, 286 insertions, 0 deletions
diff --git a/plugins/MirOTR/Libgcrypt/cipher/gostr3411-94.c b/plugins/MirOTR/Libgcrypt/cipher/gostr3411-94.c
new file mode 100644
index 0000000000..5486964db9
--- /dev/null
+++ b/plugins/MirOTR/Libgcrypt/cipher/gostr3411-94.c
@@ -0,0 +1,286 @@
+/* gostr3411-94.c - GOST R 34.11-94 hash function
+ * Copyright (C) 2012 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "g10lib.h"
+#include "bithelp.h"
+#include "cipher.h"
+#include "hash-common.h"
+
+#include "gost.h"
+
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+
+typedef struct {
+ gcry_md_block_ctx_t bctx;
+ GOST28147_context hd;
+ byte h[32];
+ byte sigma[32];
+ u32 len;
+} GOSTR3411_CONTEXT;
+
+static unsigned int
+transform (void *c, const unsigned char *data);
+
+static void
+gost3411_init (void *context, unsigned int flags)
+{
+ GOSTR3411_CONTEXT *hd = context;
+
+ (void)flags;
+
+ memset (&hd->hd, 0, sizeof(hd->hd));
+ memset (hd->h, 0, 32);
+ memset (hd->sigma, 0, 32);
+
+ hd->bctx.nblocks = 0;
+ hd->bctx.count = 0;
+ hd->bctx.blocksize = 32;
+ hd->bctx.bwrite = transform;
+}
+
+static void
+do_p (unsigned char *p, unsigned char *u, unsigned char *v)
+{
+ int i, k;
+ for (k = 0; k < 8; k++)
+ {
+ for (i = 0; i < 4; i++)
+ {
+ p[i + 4 * k] = u[8 * i + k] ^ v[8 * i + k];
+ }
+ }
+}
+
+static void
+do_a (unsigned char *u)
+{
+ unsigned char temp[8];
+ int i;
+ memcpy (temp, u, 8);
+ memmove (u, u+8, 24);
+ for (i = 0; i < 8; i++)
+ {
+ u[24 + i] = u[i] ^ temp[i];
+ }
+}
+/* apply do_a twice: 1 2 3 4 -> 3 4 1^2 2^3 */
+static void
+do_a2 (unsigned char *u)
+{
+ unsigned char temp[16];
+ int i;
+ memcpy (temp, u, 16);
+ memcpy (u, u + 16, 16);
+ for (i = 0; i < 8; i++)
+ {
+ u[16 + i] = temp[i] ^ temp[8 + i];
+ u[24 + i] = u[i] ^ temp[8 + i];
+ }
+}
+
+static void
+do_apply_c2 (unsigned char *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;
+}
+
+#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];
+
+static void
+do_phi_submix (unsigned char *e, unsigned char *x, int round)
+{
+ int i;
+ round *= 2;
+ for (i = 0; i < 32; i++)
+ {
+ e[(i + round) % 32] ^= x[i];
+ }
+}
+
+static void
+do_add (unsigned char *s, unsigned char *a)
+{
+ unsigned temp = 0;
+ int i;
+
+ for (i = 0; i < 32; i++)
+ {
+ temp = s[i] + a[i] + (temp >> 8);
+ s[i] = temp & 0xff;
+ }
+}
+
+static unsigned int
+do_hash_step (GOST28147_context *hd, unsigned char *h, unsigned char *m)
+{
+ unsigned char u[32], v[32], s[32];
+ unsigned char k[32];
+ unsigned int burn;
+ int i;
+
+ memcpy (u, h, 32);
+ memcpy (v, m, 32);
+
+ for (i = 0; i < 4; i++) {
+ do_p (k, u, v);
+
+ burn = _gcry_gost_enc_one (hd, k, s + i*8, h + i*8);
+
+ do_a (u);
+ if (i == 1)
+ do_apply_c2 (u);
+ do_a2 (v);
+ }
+
+ 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);
+ /* 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);
+ if (i == 0)
+ do_phi_submix(s, m, 12);
+ do_phi_step (s, 12);
+ if (i == 0)
+ do_phi_submix(s, h, 13);
+ do_phi_step (s, 13);
+ do_phi_step (s, 14);
+ do_phi_step (s, 15);
+ }
+
+ memcpy (h, s+20, 12);
+ memcpy (h+12, s, 20);
+
+ return /* burn_stack */ 4 * sizeof(void*) /* func call (ret addr + args) */ +
+ 4 * 32 + 2 * sizeof(int) /* stack */ +
+ max(burn /* _gcry_gost_enc_one */,
+ sizeof(void*) * 2 /* do_a2 call */ +
+ 16 + sizeof(int) /* do_a2 stack */ );
+}
+
+
+static unsigned int
+transform (void *ctx, const unsigned char *data)
+{
+ GOSTR3411_CONTEXT *hd = ctx;
+ byte m[32];
+ unsigned int burn;
+
+ memcpy (m, data, 32);
+ burn = do_hash_step (&hd->hd, hd->h, m);
+ do_add (hd->sigma, m);
+
+ return /* burn_stack */ burn + 3 * sizeof(void*) + 32 + 2 * sizeof(void*);
+}
+
+/*
+ The routine finally terminates the computation and returns the
+ digest. The handle is prepared for a new cycle, but adding bytes
+ to the handle will the destroy the returned buffer. Returns: 32
+ bytes with the message the digest. */
+static void
+gost3411_final (void *context)
+{
+ GOSTR3411_CONTEXT *hd = context;
+ size_t padlen = 0;
+ byte l[32];
+ int i;
+ u32 nblocks;
+
+ if (hd->bctx.count > 0)
+ {
+ padlen = 32 - hd->bctx.count;
+ memset (hd->bctx.buf + hd->bctx.count, 0, padlen);
+ hd->bctx.count += padlen;
+ _gcry_md_block_write (hd, NULL, 0); /* flush */;
+ }
+
+ if (hd->bctx.count != 0)
+ return; /* Something went wrong */
+
+ memset (l, 0, 32);
+
+ nblocks = hd->bctx.nblocks;
+ if (padlen)
+ {
+ nblocks --;
+ l[0] = 256 - padlen * 8;
+ }
+
+ for (i = 1; i < 32 && nblocks != 0; i++)
+ {
+ l[i] = nblocks % 256;
+ nblocks /= 256;
+ }
+
+ do_hash_step (&hd->hd, hd->h, l);
+ do_hash_step (&hd->hd, hd->h, hd->sigma);
+}
+
+static byte *
+gost3411_read (void *context)
+{
+ GOSTR3411_CONTEXT *hd = context;
+
+ return hd->h;
+}
+gcry_md_spec_t _gcry_digest_spec_gost3411_94 =
+ {
+ GCRY_MD_GOSTR3411_94, {0, 0},
+ "GOSTR3411_94", NULL, 0, NULL, 32,
+ gost3411_init, _gcry_md_block_write, gost3411_final, gost3411_read,
+ sizeof (GOSTR3411_CONTEXT)
+ };