Commit 9826eed6 authored by Dmitry Eremin-Solenikov's avatar Dmitry Eremin-Solenikov Committed by Niels Möller

Add support for GOSTHASH94CP: GOST R 34.11-94 hash with CryptoPro S-box

Hash gosthash94 implements GOST R 34.11-94 standard using S-Box defined
in the standard 'for testing purposes only'. RFC 4357 defines S-Box
(CryptoPro one) for GOST R 34.11-94 hash function that is widely used in
applications. Add separate hash function algorithm (gosthash94cp)
implementing GOST R 34.11-94 hashing using that S-Box.
Signed-off-by: default avatarDmitry Eremin-Solenikov <dbaryshkov@gmail.com>
parent 1d7bce28
......@@ -918,6 +918,7 @@ main(int argc, char **argv)
&nettle_sha3_224, &nettle_sha3_256,
&nettle_sha3_384, &nettle_sha3_512,
&nettle_ripemd160, &nettle_gosthash94,
&nettle_gosthash94cp,
NULL
};
......
This diff is collapsed.
......@@ -41,6 +41,7 @@ extern "C" {
#endif
#define gost28147_param_test_3411 nettle_gost28147_param_test_3411
#define gost28147_param_CryptoPro_3411 nettle_gost28147_param_CryptoPro_3411
struct gost28147_param
{
......@@ -48,6 +49,7 @@ struct gost28147_param
};
extern const struct gost28147_param gost28147_param_test_3411;
extern const struct gost28147_param gost28147_param_CryptoPro_3411;
#ifdef __cplusplus
}
......
......@@ -39,3 +39,6 @@
const struct nettle_hash nettle_gosthash94
= _NETTLE_HASH(gosthash94, GOSTHASH94);
const struct nettle_hash nettle_gosthash94cp
= _NETTLE_HASH(gosthash94cp, GOSTHASH94CP);
......@@ -5,6 +5,7 @@
* See also RFC 4357.
*
* Copyright: 2009-2012 Aleksey Kravchenko <rhash.admin@gmail.com>
* Copyright: 2019 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
......@@ -62,7 +63,8 @@ gosthash94_init (struct gosthash94_ctx *ctx)
* @param block the message block to process
*/
static void
gost_block_compress (struct gosthash94_ctx *ctx, const uint32_t *block)
gost_block_compress (struct gosthash94_ctx *ctx, const uint32_t *block,
const uint32_t sbox[4][256])
{
unsigned i;
uint32_t key[8], u[8], v[8], w[8], s[8];
......@@ -107,7 +109,7 @@ gost_block_compress (struct gosthash94_ctx *ctx, const uint32_t *block)
((w[5] & 0xff000000) >> 8) | (w[7] & 0xff000000);
/* encryption: s_i := E_{key_i} (h_i) */
_gost28147_encrypt_block (key, gost28147_param_test_3411.sbox, &ctx->hash[i], &s[i]);
_gost28147_encrypt_block (key, sbox, &ctx->hash[i], &s[i]);
if (i == 0)
{
......@@ -262,7 +264,8 @@ gost_block_compress (struct gosthash94_ctx *ctx, const uint32_t *block)
* @param block the 256-bit message block to process
*/
static void
gost_compute_sum_and_hash (struct gosthash94_ctx *ctx, const uint8_t *block)
gost_compute_sum_and_hash (struct gosthash94_ctx *ctx, const uint8_t *block,
const uint32_t sbox[4][256])
{
uint32_t block_le[8];
unsigned i, carry;
......@@ -278,7 +281,7 @@ gost_compute_sum_and_hash (struct gosthash94_ctx *ctx, const uint8_t *block)
}
/* update message hash */
gost_block_compress (ctx, block_le);
gost_block_compress (ctx, block_le, sbox);
}
/**
......@@ -289,9 +292,10 @@ gost_compute_sum_and_hash (struct gosthash94_ctx *ctx, const uint8_t *block)
* @param msg message chunk
* @param size length of the message chunk
*/
void
gosthash94_update (struct gosthash94_ctx *ctx,
size_t length, const uint8_t *msg)
static void
gosthash94_update_int (struct gosthash94_ctx *ctx,
size_t length, const uint8_t *msg,
const uint32_t sbox[4][256])
{
unsigned index = (unsigned) ctx->length & 31;
ctx->length += length;
......@@ -305,13 +309,13 @@ gosthash94_update (struct gosthash94_ctx *ctx,
return;
/* process partial block */
gost_compute_sum_and_hash (ctx, ctx->message);
gost_compute_sum_and_hash (ctx, ctx->message, sbox);
msg += left;
length -= left;
}
while (length >= GOSTHASH94_BLOCK_SIZE)
{
gost_compute_sum_and_hash (ctx, msg);
gost_compute_sum_and_hash (ctx, msg, sbox);
msg += GOSTHASH94_BLOCK_SIZE;
length -= GOSTHASH94_BLOCK_SIZE;
}
......@@ -322,15 +326,48 @@ gosthash94_update (struct gosthash94_ctx *ctx,
}
}
/**
* Calculate message hash.
* Can be called repeatedly with chunks of the message to be hashed.
*
* @param ctx the algorithm context containing current hashing state
* @param msg message chunk
* @param size length of the message chunk
*/
void
gosthash94_update (struct gosthash94_ctx *ctx,
size_t length, const uint8_t *msg)
{
gosthash94_update_int (ctx, length, msg,
gost28147_param_test_3411.sbox);
}
/**
* Calculate message hash.
* Can be called repeatedly with chunks of the message to be hashed.
*
* @param ctx the algorithm context containing current hashing state
* @param msg message chunk
* @param size length of the message chunk
*/
void
gosthash94cp_update (struct gosthash94_ctx *ctx,
size_t length, const uint8_t *msg)
{
gosthash94_update_int (ctx, length, msg,
gost28147_param_CryptoPro_3411.sbox);
}
/**
* Finish hashing and store message digest into given array.
*
* @param ctx the algorithm context containing current hashing state
* @param result calculated hash in binary form
*/
void
gosthash94_digest (struct gosthash94_ctx *ctx,
size_t length, uint8_t *result)
static void
gosthash94_write_digest (struct gosthash94_ctx *ctx,
size_t length, uint8_t *result,
const uint32_t sbox[4][256])
{
unsigned index = ctx->length & 31;
uint32_t msg32[8];
......@@ -341,7 +378,7 @@ gosthash94_digest (struct gosthash94_ctx *ctx,
if (index > 0)
{
memset (ctx->message + index, 0, 32 - index);
gost_compute_sum_and_hash (ctx, ctx->message);
gost_compute_sum_and_hash (ctx, ctx->message, sbox);
}
/* hash the message length and the sum */
......@@ -349,10 +386,26 @@ gosthash94_digest (struct gosthash94_ctx *ctx,
msg32[1] = ctx->length >> 29;
memset (msg32 + 2, 0, sizeof (uint32_t) * 6);
gost_block_compress (ctx, msg32);
gost_block_compress (ctx, ctx->sum);
gost_block_compress (ctx, msg32, sbox);
gost_block_compress (ctx, ctx->sum, sbox);
/* convert hash state to result bytes */
_nettle_write_le32(length, result, ctx->hash);
gosthash94_init (ctx);
}
void
gosthash94_digest (struct gosthash94_ctx *ctx,
size_t length, uint8_t *result)
{
gosthash94_write_digest (ctx, length, result,
gost28147_param_test_3411.sbox);
}
void
gosthash94cp_digest (struct gosthash94_ctx *ctx,
size_t length, uint8_t *result)
{
gosthash94_write_digest (ctx, length, result,
gost28147_param_CryptoPro_3411.sbox);
}
......@@ -72,11 +72,17 @@ extern "C" {
#define gosthash94_update nettle_gosthash94_update
#define gosthash94_digest nettle_gosthash94_digest
#define gosthash94cp_update nettle_gosthash94cp_update
#define gosthash94cp_digest nettle_gosthash94cp_digest
#define GOSTHASH94_BLOCK_SIZE 32
#define GOSTHASH94_DIGEST_SIZE 32
/* For backwards compatibility */
#define GOSTHASH94_DATA_SIZE GOSTHASH94_BLOCK_SIZE
#define GOSTHASH94CP_BLOCK_SIZE GOSTHASH94_BLOCK_SIZE
#define GOSTHASH94CP_DIGEST_SIZE GOSTHASH94_DIGEST_SIZE
struct gosthash94_ctx
{
uint32_t hash[8]; /* algorithm 256-bit state */
......@@ -84,6 +90,7 @@ struct gosthash94_ctx
uint64_t length; /* number of processed bytes */
uint8_t message[GOSTHASH94_BLOCK_SIZE]; /* 256-bit buffer for leftovers */
};
#define gosthash94cp_ctx gosthash94_ctx
void gosthash94_init(struct gosthash94_ctx *ctx);
void gosthash94_update(struct gosthash94_ctx *ctx,
......@@ -91,6 +98,12 @@ void gosthash94_update(struct gosthash94_ctx *ctx,
void gosthash94_digest(struct gosthash94_ctx *ctx,
size_t length, uint8_t *result);
#define gosthash94cp_init gosthash94_init
void gosthash94cp_update(struct gosthash94_ctx *ctx,
size_t length, const uint8_t *msg);
void gosthash94cp_digest(struct gosthash94_ctx *ctx,
size_t length, uint8_t *result);
#ifdef __cplusplus
}
#endif
......
......@@ -130,6 +130,7 @@ extern const struct nettle_hash nettle_md2;
extern const struct nettle_hash nettle_md4;
extern const struct nettle_hash nettle_md5;
extern const struct nettle_hash nettle_gosthash94;
extern const struct nettle_hash nettle_gosthash94cp;
extern const struct nettle_hash nettle_ripemd160;
extern const struct nettle_hash nettle_sha1;
extern const struct nettle_hash nettle_sha224;
......
......@@ -1039,12 +1039,17 @@ This function also resets the context in the same way as
@end deftypefun
@subsubsection @acronym{GOSTHASH94}
@subsubsection @acronym{GOSTHASH94 and GOSTHASH94CP}
The GOST94 or GOST R 34.11-94 hash algorithm is a Soviet-era algorithm
used in Russian government standards (see @cite{RFC 4357}).
It outputs message digests of 256 bits, or 32 octets.
Nettle defines GOSTHASH94 in @file{<nettle/gosthash94.h>}.
It outputs message digests of 256 bits, or 32 octets. The standard itself
does not fix the S-box used by the hash algorith, so there are two popular
variants (the testing S-box from the standard itself and the S-box defined
by CryptoPro company, see RFC 4357). Nettle provides support for the former
S-box in the form of GOSTHASH94 hash algorithm and for the latter in the
form of GOSTHASH94CP hash algorithm.
Nettle defines GOSTHASH94 and GOSTHASH94CP in @file{<nettle/gosthash94.h>}.
@deftp {Context struct} {struct gosthash94_ctx}
@end deftp
......@@ -1075,6 +1080,35 @@ This function also resets the context in the same way as
@code{gosthash94_init}.
@end deftypefun
@deftp {Context struct} {struct gosthash94cp_ctx}
@end deftp
@defvr Constant GOSTHASH94CP_DIGEST_SIZE
The size of a GOSTHASH94CP digest, i.e. 32.
@end defvr
@defvr Constant GOSTHASH94CP_BLOCK_SIZE
The internal block size of GOSTHASH94CP, i.e., 32.
@end defvr
@deftypefun void gosthash94cp_init (struct gosthash94cp_ctx *@var{ctx})
Initialize the GOSTHASH94CP state.
@end deftypefun
@deftypefun void gosthash94cp_update (struct gosthash94cp_ctx *@var{ctx}, size_t @var{length}, const uint8_t *@var{data})
Hash some more data.
@end deftypefun
@deftypefun void gosthash94cp_digest (struct gosthash94cp_ctx *@var{ctx}, size_t @var{length}, uint8_t *@var{digest})
Performs final processing and extracts the message digest, writing it
to @var{digest}. @var{length} may be smaller than
@code{GOSTHASH94CP_DIGEST_SIZE}, in which case only the first @var{length}
octets of the digest are written.
This function also resets the context in the same way as
@code{gosthash94cp_init}.
@end deftypefun
@node nettle_hash abstraction,, Legacy hash functions, Hash functions
@comment node-name, next, previous, up
@subsection The @code{struct nettle_hash} abstraction
......@@ -1104,6 +1138,7 @@ The last three attributes are function pointers, of types
@deftypevrx {Constant Struct} {struct nettle_hash} nettle_sha512
@deftypevrx {Constant Struct} {struct nettle_hash} nettle_sha3_256
@deftypevrx {Constant Struct} {struct nettle_hash} nettle_gosthash94
@deftypevrx {Constant Struct} {struct nettle_hash} nettle_gosthash94cp
These are all the hash functions that Nettle implements.
@end deftypevr
......
......@@ -17,4 +17,16 @@ test_main(void)
test_hash(&nettle_gosthash94, SDATA(""),
SHEX("ce85b99cc46752fffee35cab9a7b0278abb4c2d2055cff685af4912c49490f8d"));
test_hash(&nettle_gosthash94cp, SDATA("The quick brown fox jumps over the lazy dog"),
SHEX("9004294a361a508c586fe53d1f1b02746765e71b765472786e4770d565830a76"));
test_hash(&nettle_gosthash94cp, SDATA("message digest"),
SHEX("bc6041dd2aa401ebfa6e9886734174febdb4729aa972d60f549ac39b29721ba0"));
test_hash(&nettle_gosthash94cp, SDATA("a"),
SHEX("e74c52dd282183bf37af0079c9f78055715a103f17e3133ceff1aacf2f403011"));
test_hash(&nettle_gosthash94cp, SDATA(""),
SHEX("981e5f3ca30c841487830f84fb433e13ac1101569b9c13584ac483234cd656c0"));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment