diff options
author | René Schümann <white06tiger@gmail.com> | 2015-03-20 12:32:29 +0000 |
---|---|---|
committer | René Schümann <white06tiger@gmail.com> | 2015-03-20 12:32:29 +0000 |
commit | 539705d58fc39a28388ff18c695dd406f4ffd1d9 (patch) | |
tree | 51db7a37a66c09f41734ba5573d972aae9f30d71 /plugins/MirOTR/Libgcrypt/cipher/gostr3411-94.c | |
parent | 90171f125f36488dc08f5cfe0b0d4b78d995f08d (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.c | 286 |
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) + }; |