Commit b6b9b6c3 authored by Niels Möller's avatar Niels Möller
Browse files

Add skein512 hash funcction.

parent 4f136e53
2018-01-01 Niels Möller <nisse@lysator.liu.se>
* skein512.c: New file.
* skein512-meta.c: New file, new nettle_hash.
* nettle-meta.h (nettle_skein512): Declare it.
* testsuite/skein.awk: New script for processing official test
vectors.
* testsuite/skein512-test.c (test_main): Add more test vectors.
* examples/nettle-benchmark.c (main): Add benchmarking of
skein512.
* skein.h (_SKEIN256_NKEYS): Reduce from 6 to 5 (repeated subkeys
no longer used).
* skein256.c (_skein256_expand): Update accordingly.
......
......@@ -130,7 +130,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
sha3-384.c sha3-384-meta.c sha3-512.c sha3-512-meta.c\
serpent-set-key.c serpent-encrypt.c serpent-decrypt.c \
serpent-meta.c skein256.c skein256-internal.c skein256-meta.c \
skein512-internal.c \
skein512.c skein512-internal.c skein512-meta.c \
twofish.c twofish-meta.c \
umac-nh.c umac-nh-n.c umac-l2.c umac-l3.c \
umac-poly64.c umac-poly128.c umac-set-key.c \
......
......@@ -766,7 +766,7 @@ main(int argc, char **argv)
&nettle_sha512_224, &nettle_sha512_256,
&nettle_sha3_224, &nettle_sha3_256,
&nettle_sha3_384, &nettle_sha3_512,
&nettle_skein256,
&nettle_skein256, &nettle_skein512,
&nettle_ripemd160, &nettle_gosthash94,
NULL
};
......
......@@ -159,6 +159,7 @@ extern const struct nettle_hash nettle_sha3_256;
extern const struct nettle_hash nettle_sha3_384;
extern const struct nettle_hash nettle_sha3_512;
extern const struct nettle_hash nettle_skein256;
extern const struct nettle_hash nettle_skein512;
struct nettle_aead
{
......
......@@ -44,8 +44,12 @@ extern "C" {
#define skein256_init nettle_skein256_init
#define skein256_update nettle_skein256_update
#define skein256_digest nettle_skein256_digest
#define skein512_init nettle_skein512_init
#define skein512_update nettle_skein512_update
#define skein512_digest nettle_skein512_digest
#define _skein256_expand _nettle_skein256_expand
#define _skein256_block _nettle_skein256_block
#define _skein512_expand _nettle_skein512_expand
#define _skein512_block _nettle_skein512_block
#define SKEIN256_BLOCK_SIZE 32
......@@ -90,6 +94,29 @@ skein256_digest(struct skein256_ctx *ctx,
#define _SKEIN512_LENGTH 8
#define _SKEIN512_NKEYS 9
struct skein512_ctx {
uint64_t state[_SKEIN512_NKEYS];
/* Current implementation limited to message size <= 2^70 - 64 bytes,
while the specification allows up to 2^96 - 1 bytes.*/
uint64_t count; /* Block count */
uint8_t block[SKEIN512_BLOCK_SIZE];
unsigned index;
};
void
skein512_init(struct skein512_ctx *ctx);
void
skein512_update(struct skein512_ctx *ctx,
size_t length,
const uint8_t *data);
void
skein512_digest(struct skein512_ctx *ctx,
size_t length,
uint8_t *digest);
#define _SKEIN_C240 0x1BD11BDAA9FC1A22ULL
void
......@@ -101,6 +128,9 @@ _skein256_block (uint64_t dst[_SKEIN256_LENGTH],
const uint64_t tweak[_SKEIN_NTWEAK],
const uint8_t src[SKEIN256_BLOCK_SIZE]);
void
_skein512_expand(uint64_t keys[_SKEIN512_NKEYS]);
void
_skein512_block (uint64_t dst[_SKEIN512_LENGTH],
const uint64_t keys[_SKEIN512_NKEYS],
......
/* skein512-meta.c
Copyright (C) 2018 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle 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
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "nettle-meta.h"
#include "skein.h"
const struct nettle_hash nettle_skein512
= _NETTLE_HASH(skein512, SKEIN512);
/* skein512.c
Copyright (C) 2016, 2017, 2018 Niels Möller
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle 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
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include <string.h>
#include "skein.h"
#include "nettle-write.h"
void
_skein512_expand(uint64_t keys[_SKEIN512_NKEYS])
{
uint64_t sum;
unsigned i;
for (i = 0, sum = _SKEIN_C240; i < _SKEIN512_LENGTH; i++)
sum ^= keys[i];
keys[_SKEIN512_LENGTH] = sum;
/* Repeat keys, for simpler indexing. */
for (i = _SKEIN512_LENGTH + 1; i < _SKEIN512_NKEYS; i++)
keys[i] = keys[i-9];
}
void
skein512_init(struct skein512_ctx *ctx)
{
static const uint64_t G0[_SKEIN512_LENGTH] = {
0x4903ADFF749C51CEull, 0x0D95DE399746DF03ull,
0x8FD1934127C79BCEull, 0x9A255629FF352CB1ull,
0x5DB62599DF6CA7B0ull, 0xEABE394CA9D5C3F4ull,
0x991112C71A75B523ull, 0xAE18A40B660FCC33ull,
};
memcpy (ctx->state, G0, sizeof(G0));
ctx->count = 0;
ctx->index = 0;
}
static void
skein512_process_block(struct skein512_ctx *ctx,
unsigned tag, unsigned length,
const uint8_t *data)
{
/* Expand key */
uint64_t tweak[_SKEIN_NTWEAK];
tag |= ((ctx->count == 0) << 6);
tweak[0] = (ctx->count << 6) + length;
tweak[1] = (ctx->count >> 58) | ((uint64_t) tag << 56);
_skein512_expand(ctx->state);
_skein512_block(ctx->state, ctx->state, tweak, data);
ctx->count++;
/* Wraparound not handled (limited message size). */
assert (ctx->count > 0);
}
void
skein512_update(struct skein512_ctx *ctx,
size_t length,
const uint8_t *data)
{
if (ctx->index > 0)
{
unsigned left = SKEIN512_BLOCK_SIZE - ctx->index;
if (length <= left)
{
memcpy (ctx->block + ctx->index, data, length);
ctx->index += length;
return;
}
memcpy (ctx->block + ctx->index, data, left);
data += left;
length -= left;
assert (length > 0);
skein512_process_block(ctx, 0x30, SKEIN512_BLOCK_SIZE, ctx->block);
}
while (length > SKEIN512_BLOCK_SIZE)
{
skein512_process_block(ctx, 0x30, SKEIN512_BLOCK_SIZE, data);
data += SKEIN512_BLOCK_SIZE;
length -= SKEIN512_BLOCK_SIZE;
}
assert (length <= SKEIN512_BLOCK_SIZE);
memcpy (ctx->block, data, length);
ctx->index = length;
}
void
skein512_digest(struct skein512_ctx *ctx,
size_t length,
uint8_t *digest)
{
static const uint8_t zeros[SKEIN512_BLOCK_SIZE];
/* FIXME: Should be always true. */
if (ctx->index > 0 || ctx->count == 0)
{
memset (ctx->block + ctx->index, 0,
SKEIN512_BLOCK_SIZE - ctx->index);
skein512_process_block(ctx, 0xb0, ctx->index, ctx->block);
}
/* Reset count for output processing. */
ctx->count = 0;
skein512_process_block(ctx, 0xff, 8, zeros);
_nettle_write_le64(length, digest, ctx->state);
skein512_init(ctx);
}
#! /usr/bin/awk -f
# This script is used to process the Skein test vectors, from
# http://www.skein-hash.info/sites/default/files/NIST_CD_102610.zip
/^Len/ { len = $3 }
/^Msg/ { msg = $3 }
/^MD/ { md = $3;
if (len % 8 == 0)
printf("test_hash(&nettle_skeinxxx, /* %d octets */\nSHEX(\"%s\"),\nSHEX(\"%s\"));\n",
len / 8, msg, md);
}
This diff is collapsed.
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