diff --git a/cipher/gost.h b/cipher/gost.h
index 025119c9..04c2f85e 100644
--- a/cipher/gost.h
+++ b/cipher/gost.h
@@ -1,32 +1,32 @@
/* gost.h - GOST 28147-89 implementation
* 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 .
*/
#ifndef _GCRY_GOST_H
#define _GCRY_GOST_H
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 */
-unsigned int _gcry_gost_enc_data (GOST28147_context *c, const u32 *key,
+unsigned int _gcry_gost_enc_data (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 85d398d7..db7e9412 100644
--- a/cipher/gost28147.c
+++ b/cipher/gost28147.c
@@ -1,229 +1,229 @@
/* gost28147.c - GOST 28147-89 implementation for Libgcrypt
* 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 .
*/
/* GOST 28147-89 defines several modes of encryption:
* - ECB which should be used only for key transfer
* - CFB mode
* - OFB-like mode with additional transformation on keystream
* RFC 5830 names this 'counter encryption' mode
* Original GOST text uses the term 'gammirovanie'
* - MAC mode
*
* This implementation handles ECB and CFB modes via usual libgcrypt handling.
* OFB-like and MAC modes are unsupported.
*/
#include
#include "types.h"
#include "g10lib.h"
#include "cipher.h"
#include "bufhelp.h"
#include "gost.h"
#include "gost-sb.h"
static gcry_err_code_t
gost_setkey (void *c, const byte *key, unsigned keylen,
gcry_cipher_hd_t hd)
{
int i;
GOST28147_context *ctx = c;
(void)hd;
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] = buf_get_le32(&key[4*i]);
}
return GPG_ERR_NO_ERROR;
}
static u32
gost_val (u32 subkey, u32 cm1, const u32 *sbox)
{
cm1 += subkey;
cm1 = sbox[0*256 + ((cm1 >> 0) & 0xff)] |
sbox[1*256 + ((cm1 >> 8) & 0xff)] |
sbox[2*256 + ((cm1 >> 16) & 0xff)] |
sbox[3*256 + ((cm1 >> 24) & 0xff)];
return cm1;
}
static unsigned int
_gost_encrypt_data (const u32 *sbox, const u32 *key, u32 *o1, u32 *o2, u32 n1, u32 n2)
{
n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox);
n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox);
n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox);
n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox);
n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox);
n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox);
n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox);
n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox);
n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox);
n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox);
n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox);
n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox);
n2 ^= gost_val (key[7], n1, sbox); n1 ^= gost_val (key[6], n2, sbox);
n2 ^= gost_val (key[5], n1, sbox); n1 ^= gost_val (key[4], n2, sbox);
n2 ^= gost_val (key[3], n1, sbox); n1 ^= gost_val (key[2], n2, sbox);
n2 ^= gost_val (key[1], n1, sbox); n1 ^= gost_val (key[0], n2, sbox);
*o1 = n2;
*o2 = n1;
return /* burn_stack */ 4*sizeof(void*) /* func call */ +
3*sizeof(void*) /* stack */ +
4*sizeof(void*) /* gost_val call */;
}
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->sbox, ctx->key, &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,
+unsigned int _gcry_gost_enc_data (const u32 *key,
u32 *o1, u32 *o2, u32 n1, u32 n2, int cryptopro)
{
const u32 *sbox;
if (cryptopro)
sbox = sbox_CryptoPro_3411;
else
sbox = sbox_test_3411;
return _gost_encrypt_data (sbox, key, o1, o2, n1, n2) + 7 * sizeof(void *);
}
static unsigned int
gost_decrypt_block (void *c, byte *outbuf, const byte *inbuf)
{
GOST28147_context *ctx = c;
u32 n1, n2;
const u32 *sbox = ctx->sbox;
n1 = buf_get_le32 (inbuf);
n2 = buf_get_le32 (inbuf+4);
n2 ^= gost_val (ctx->key[0], n1, sbox); n1 ^= gost_val (ctx->key[1], n2, sbox);
n2 ^= gost_val (ctx->key[2], n1, sbox); n1 ^= gost_val (ctx->key[3], n2, sbox);
n2 ^= gost_val (ctx->key[4], n1, sbox); n1 ^= gost_val (ctx->key[5], n2, sbox);
n2 ^= gost_val (ctx->key[6], n1, sbox); n1 ^= gost_val (ctx->key[7], n2, sbox);
n2 ^= gost_val (ctx->key[7], n1, sbox); n1 ^= gost_val (ctx->key[6], n2, sbox);
n2 ^= gost_val (ctx->key[5], n1, sbox); n1 ^= gost_val (ctx->key[4], n2, sbox);
n2 ^= gost_val (ctx->key[3], n1, sbox); n1 ^= gost_val (ctx->key[2], n2, sbox);
n2 ^= gost_val (ctx->key[1], n1, sbox); n1 ^= gost_val (ctx->key[0], n2, sbox);
n2 ^= gost_val (ctx->key[7], n1, sbox); n1 ^= gost_val (ctx->key[6], n2, sbox);
n2 ^= gost_val (ctx->key[5], n1, sbox); n1 ^= gost_val (ctx->key[4], n2, sbox);
n2 ^= gost_val (ctx->key[3], n1, sbox); n1 ^= gost_val (ctx->key[2], n2, sbox);
n2 ^= gost_val (ctx->key[1], n1, sbox); n1 ^= gost_val (ctx->key[0], n2, sbox);
n2 ^= gost_val (ctx->key[7], n1, sbox); n1 ^= gost_val (ctx->key[6], n2, sbox);
n2 ^= gost_val (ctx->key[5], n1, sbox); n1 ^= gost_val (ctx->key[4], n2, sbox);
n2 ^= gost_val (ctx->key[3], n1, sbox); n1 ^= gost_val (ctx->key[2], n2, sbox);
n2 ^= gost_val (ctx->key[1], n1, sbox); n1 ^= gost_val (ctx->key[0], n2, sbox);
buf_put_le32 (outbuf+0, n2);
buf_put_le32 (outbuf+4, n1);
return /* burn_stack */ 4*sizeof(void*) /* func call */ +
3*sizeof(void*) /* stack */ +
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 }, */
{ "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, oids_gost28147, 8, 256,
sizeof (GOST28147_context),
gost_setkey,
gost_encrypt_block,
gost_decrypt_block,
NULL, NULL, NULL, gost_set_extra_info,
};
diff --git a/cipher/gostr3411-94.c b/cipher/gostr3411-94.c
index c5a0aef6..7cf0637e 100644
--- a/cipher/gostr3411-94.c
+++ b/cipher/gostr3411-94.c
@@ -1,385 +1,383 @@
/* 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 .
*/
#include
#include
#include
#include
#include "g10lib.h"
#include "bithelp.h"
#include "bufhelp.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;
union {
u32 h[8];
byte result[32];
};
u32 sigma[8];
u32 len;
int cryptopro;
} GOSTR3411_CONTEXT;
static unsigned int
transform (void *c, const unsigned char *data, size_t nblks);
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_shift = _gcry_ctz(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
do_p (u32 *p, u32 *u, u32 *v)
{
int k;
u32 t[8];
for (k = 0; k < 8; k++)
t[k] = u[k] ^ v[k];
k = 0;
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;
k = 1;
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;
k = 2;
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;
k = 3;
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 (u32 *u)
{
u32 t[2];
int 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 (u32 *u)
{
u32 t[4];
int i;
memcpy (t, u, 16);
memcpy (u, u + 4, 16);
for (i = 0; i < 2; i++)
{
u[4+i] = t[i] ^ t[i + 2];
u[6+i] = u[i] ^ t[i + 2];
}
}
static void
do_apply_c2 (u32 *u)
{
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_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_chi_submix12 (u32 *e, u32 *x)
{
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 (u32 *s, u32 *a)
{
u32 carry = 0;
int i;
for (i = 0; i < 8; i++)
{
u32 op = carry + a[i];
s[i] += op;
carry = (a[i] > op) || (op > s[i]);
}
}
static unsigned int
do_hash_step (GOSTR3411_CONTEXT *hd, u32 *h, u32 *m)
{
u32 u[8], v[8];
u32 s[8];
u32 k[8];
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_data (&hd->hd, k, &s[2*i], &s[2*i+1], h[2*i], h[2*i+1], hd->cryptopro);
+ burn = _gcry_gost_enc_data (k, &s[2*i], &s[2*i+1], h[2*i], h[2*i+1], hd->cryptopro);
do_a (u);
if (i == 1)
do_apply_c2 (u);
do_a2 (v);
}
for (i = 0; i < 5; i++)
{
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_chi_doublestep (s, 5);
if (i == 0)
do_chi_submix12(s, m);
do_chi_step12 (s);
if (i == 0)
do_chi_submix13(s, h);
do_chi_step13 (s);
do_chi_doublestep (s, 7);
}
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 */ +
max(burn /* _gcry_gost_enc_one */,
sizeof(void*) * 2 /* do_a2 call */ +
16 + sizeof(int) /* do_a2 stack */ );
}
static unsigned int
transform_blk (void *ctx, const unsigned char *data)
{
GOSTR3411_CONTEXT *hd = ctx;
u32 m[8];
unsigned int burn;
int i;
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);
return /* burn_stack */ burn + 3 * sizeof(void*) + 32 + 2 * sizeof(void*);
}
static unsigned int
transform ( void *c, const unsigned char *data, size_t nblks )
{
unsigned int burn;
do
{
burn = transform_blk (c, data);
data += 32;
}
while (--nblks);
return burn;
}
/*
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;
u32 l[8];
int i;
MD_NBLOCKS_TYPE 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;
}
l[0] |= nblocks << 8;
nblocks >>= 24;
for (i = 1; i < 8 && nblocks != 0; i++)
{
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 *
gost3411_read (void *context)
{
GOSTR3411_CONTEXT *hd = context;
return hd->result;
}
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,
gost3411_init, _gcry_md_block_write, gost3411_final, gost3411_read, NULL,
NULL, NULL,
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, NULL,
NULL, NULL,
sizeof (GOSTR3411_CONTEXT)
};