xof: Implemented SHAKE128 and SHAKE256 Extended Output Functions
This commit is contained in:
@@ -11,6 +11,9 @@ plugin_LTLIBRARIES = libstrongswan-sha3.la
|
||||
endif
|
||||
|
||||
libstrongswan_sha3_la_SOURCES = \
|
||||
sha3_plugin.h sha3_plugin.c sha3_hasher.c sha3_hasher.h
|
||||
sha3_plugin.h sha3_plugin.c \
|
||||
sha3_hasher.c sha3_hasher.h \
|
||||
sha3_shake.h sha3_shake.c \
|
||||
sha3_keccak.h sha3_keccak.c
|
||||
|
||||
libstrongswan_sha3_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
@@ -1,53 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Andreas Steffen
|
||||
* Copyright (C) 2015-2016 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* Based on the implementation by the Keccak, Keyak and Ketje Teams, namely,
|
||||
* Guido Bertoni, Joan Daemen, Michaël Peeters, Gilles Van Assche and
|
||||
* Ronny Van Keer, hereby denoted as "the implementer".
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of 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. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* To the extent possible under law, the implementer has waived all copyright
|
||||
* and related or neighboring rights to the source code in this file.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "sha3_hasher.h"
|
||||
#include "sha3_keccak.h"
|
||||
|
||||
typedef struct private_sha3_hasher_t private_sha3_hasher_t;
|
||||
|
||||
#define KECCAK_STATE_SIZE 200 /* bytes */
|
||||
#define KECCAK_MAX_RATE 144 /* bytes */
|
||||
#define DELIMITED_SUFFIX 0x06
|
||||
|
||||
static const uint64_t round_constants[] = {
|
||||
0x0000000000000001ULL,
|
||||
0x0000000000008082ULL,
|
||||
0x800000000000808aULL,
|
||||
0x8000000080008000ULL,
|
||||
0x000000000000808bULL,
|
||||
0x0000000080000001ULL,
|
||||
0x8000000080008081ULL,
|
||||
0x8000000000008009ULL,
|
||||
0x000000000000008aULL,
|
||||
0x0000000000000088ULL,
|
||||
0x0000000080008009ULL,
|
||||
0x000000008000000aULL,
|
||||
0x000000008000808bULL,
|
||||
0x800000000000008bULL,
|
||||
0x8000000000008089ULL,
|
||||
0x8000000000008003ULL,
|
||||
0x8000000000008002ULL,
|
||||
0x8000000000000080ULL,
|
||||
0x000000000000800aULL,
|
||||
0x800000008000000aULL,
|
||||
0x8000000080008081ULL,
|
||||
0x8000000000008080ULL,
|
||||
0x0000000080000001ULL,
|
||||
0x8000000080008008ULL
|
||||
};
|
||||
|
||||
/**
|
||||
* Private data structure with hashing context for SHA-3
|
||||
*/
|
||||
@@ -64,309 +36,16 @@ struct private_sha3_hasher_t {
|
||||
hash_algorithm_t algorithm;
|
||||
|
||||
/**
|
||||
* Internal state of 1600 bits as defined by FIPS-202
|
||||
* SHA-3 Keccak state
|
||||
*/
|
||||
uint8_t state[KECCAK_STATE_SIZE];
|
||||
|
||||
/**
|
||||
* Rate in bytes
|
||||
*/
|
||||
u_int rate;
|
||||
|
||||
/**
|
||||
* Rate input buffer
|
||||
*/
|
||||
uint8_t rate_buffer[KECCAK_MAX_RATE];
|
||||
|
||||
/**
|
||||
* Index pointing to the current position in the rate buffer
|
||||
*/
|
||||
u_int rate_index;
|
||||
sha3_keccak_t *keccak;
|
||||
|
||||
};
|
||||
|
||||
#if BYTE_ORDER != LITTLE_ENDIAN
|
||||
/**
|
||||
* Function to load a 64-bit value using the little-endian (LE) convention.
|
||||
* On a LE platform, this could be greatly simplified using a cast.
|
||||
*/
|
||||
static uint64_t load64(const uint8_t *x)
|
||||
{
|
||||
int i;
|
||||
uint64_t u = 0;
|
||||
|
||||
for (i = 7; i >= 0; --i)
|
||||
{
|
||||
u <<= 8;
|
||||
u |= x[i];
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to store a 64-bit value using the little-endian (LE) convention.
|
||||
* On a LE platform, this could be greatly simplified using a cast.
|
||||
*/
|
||||
static void store64(uint8_t *x, uint64_t u)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
x[i] = u;
|
||||
u >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to XOR into a 64-bit value using the little-endian (LE) convention.
|
||||
* On a LE platform, this could be greatly simplified using a cast.
|
||||
*/
|
||||
static void xor64(uint8_t *x, uint64_t u)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
x[i] ^= u;
|
||||
u >>= 8;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Some macros used by the Keccak-f[1600] permutation.
|
||||
*/
|
||||
#define ROL64(a, offset) ((((uint64_t)a) << offset) ^ (((uint64_t)a) >> (64-offset)))
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define readLane(i) (((uint64_t*)state)[i])
|
||||
#define writeLane(i, lane) (((uint64_t*)state)[i]) = (lane)
|
||||
#define XORLane(i, lane) (((uint64_t*)state)[i]) ^= (lane)
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
#define readLane(i) load64((uint8_t*)state+sizeof(uint64_t)*i))
|
||||
#define writeLane(i, lane) store64((uint8_t*)state+sizeof(uint64_t)*i, lane)
|
||||
#define XORLane(i, lane) xor64((uint8_t*)state+sizeof(uint64_t)*i, lane)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Function that computes the Keccak-f[1600] permutation on the given state.
|
||||
*/
|
||||
static void keccak_f1600_state_permute(void *state)
|
||||
{
|
||||
int round;
|
||||
|
||||
for (round = 0; round < 24; round++)
|
||||
{
|
||||
{ /* θ step (see [Keccak Reference, Section 2.3.2]) */
|
||||
|
||||
uint64_t C[5], D;
|
||||
|
||||
/* Compute the parity of the columns */
|
||||
C[0] = readLane(0) ^ readLane( 5) ^ readLane(10)
|
||||
^ readLane(15) ^ readLane(20);
|
||||
C[1] = readLane(1) ^ readLane( 6) ^ readLane(11)
|
||||
^ readLane(16) ^ readLane(21);
|
||||
C[2] = readLane(2) ^ readLane( 7) ^ readLane(12)
|
||||
^ readLane(17) ^ readLane(22);
|
||||
C[3] = readLane(3) ^ readLane( 8) ^ readLane(13)
|
||||
^ readLane(18) ^ readLane(23);
|
||||
C[4] = readLane(4) ^ readLane( 9) ^ readLane(14)
|
||||
^ readLane(19) ^ readLane(24);
|
||||
|
||||
/* Compute and add the θ effect to the whole column */
|
||||
D = C[4] ^ ROL64(C[1], 1);
|
||||
XORLane( 0, D);
|
||||
XORLane( 5, D);
|
||||
XORLane(10, D);
|
||||
XORLane(15, D);
|
||||
XORLane(20, D);
|
||||
|
||||
D = C[0] ^ ROL64(C[2], 1);
|
||||
XORLane( 1, D);
|
||||
XORLane( 6, D);
|
||||
XORLane(11, D);
|
||||
XORLane(16, D);
|
||||
XORLane(21, D);
|
||||
|
||||
D = C[1] ^ ROL64(C[3], 1);
|
||||
XORLane( 2, D);
|
||||
XORLane( 7, D);
|
||||
XORLane(12, D);
|
||||
XORLane(17, D);
|
||||
XORLane(22, D);
|
||||
|
||||
D = C[2] ^ ROL64(C[4], 1);
|
||||
XORLane( 3, D);
|
||||
XORLane( 8, D);
|
||||
XORLane(13, D);
|
||||
XORLane(18, D);
|
||||
XORLane(23, D);
|
||||
|
||||
D = C[3] ^ ROL64(C[0], 1);
|
||||
XORLane( 4, D);
|
||||
XORLane( 9, D);
|
||||
XORLane(14, D);
|
||||
XORLane(19, D);
|
||||
XORLane(24, D);
|
||||
}
|
||||
|
||||
{ /* ρ and π steps (see [Keccak Reference, Sections 2.3.3 and 2.3.4]) */
|
||||
|
||||
uint64_t t1, t2;
|
||||
|
||||
t1 = readLane( 1);
|
||||
|
||||
t2 = readLane(10);
|
||||
writeLane(10, ROL64(t1, 1));
|
||||
|
||||
t1 = readLane( 7);
|
||||
writeLane( 7, ROL64(t2, 3));
|
||||
|
||||
t2 = readLane(11);
|
||||
writeLane(11, ROL64(t1, 6));
|
||||
|
||||
t1 = readLane(17);
|
||||
writeLane(17, ROL64(t2, 10));
|
||||
|
||||
t2 = readLane(18);
|
||||
writeLane(18, ROL64(t1, 15));
|
||||
|
||||
t1 = readLane( 3);
|
||||
writeLane( 3, ROL64(t2, 21));
|
||||
|
||||
t2 = readLane( 5);
|
||||
writeLane( 5, ROL64(t1, 28));
|
||||
|
||||
t1 = readLane(16);
|
||||
writeLane(16, ROL64(t2, 36));
|
||||
|
||||
t2 = readLane( 8);
|
||||
writeLane( 8, ROL64(t1, 45));
|
||||
|
||||
t1 = readLane(21);
|
||||
writeLane(21, ROL64(t2, 55));
|
||||
|
||||
t2 = readLane(24);
|
||||
writeLane(24, ROL64(t1, 2));
|
||||
|
||||
t1 = readLane( 4);
|
||||
writeLane( 4, ROL64(t2, 14));
|
||||
|
||||
t2 = readLane(15);
|
||||
writeLane(15, ROL64(t1, 27));
|
||||
|
||||
t1 = readLane(23);
|
||||
writeLane(23, ROL64(t2, 41));
|
||||
|
||||
t2 = readLane(19);
|
||||
writeLane(19, ROL64(t1, 56));
|
||||
|
||||
t1 = readLane(13);
|
||||
writeLane(13, ROL64(t2, 8));
|
||||
|
||||
t2 = readLane(12);
|
||||
writeLane(12, ROL64(t1, 25));
|
||||
|
||||
t1 = readLane( 2);
|
||||
writeLane( 2, ROL64(t2, 43));
|
||||
|
||||
t2 = readLane(20);
|
||||
writeLane(20, ROL64(t1, 62));
|
||||
|
||||
t1 = readLane(14);
|
||||
writeLane(14, ROL64(t2, 18));
|
||||
|
||||
t2 = readLane(22);
|
||||
writeLane(22, ROL64(t1, 39));
|
||||
|
||||
t1 = readLane( 9);
|
||||
writeLane( 9, ROL64(t2, 61));
|
||||
|
||||
t2 = readLane( 6);
|
||||
writeLane( 6, ROL64(t1, 20));
|
||||
|
||||
writeLane( 1, ROL64(t2, 44));
|
||||
}
|
||||
|
||||
{ /* χ step (see [Keccak Reference, Section 2.3.1]) */
|
||||
|
||||
uint64_t t[5];
|
||||
|
||||
t[0] = readLane(0);
|
||||
t[1] = readLane(1);
|
||||
t[2] = readLane(2);
|
||||
t[3] = readLane(3);
|
||||
t[4] = readLane(4);
|
||||
|
||||
writeLane(0, t[0] ^ ((~t[1]) & t[2]));
|
||||
writeLane(1, t[1] ^ ((~t[2]) & t[3]));
|
||||
writeLane(2, t[2] ^ ((~t[3]) & t[4]));
|
||||
writeLane(3, t[3] ^ ((~t[4]) & t[0]));
|
||||
writeLane(4, t[4] ^ ((~t[0]) & t[1]));
|
||||
|
||||
t[0] = readLane(5);
|
||||
t[1] = readLane(6);
|
||||
t[2] = readLane(7);
|
||||
t[3] = readLane(8);
|
||||
t[4] = readLane(9);
|
||||
|
||||
writeLane(5, t[0] ^ ((~t[1]) & t[2]));
|
||||
writeLane(6, t[1] ^ ((~t[2]) & t[3]));
|
||||
writeLane(7, t[2] ^ ((~t[3]) & t[4]));
|
||||
writeLane(8, t[3] ^ ((~t[4]) & t[0]));
|
||||
writeLane(9, t[4] ^ ((~t[0]) & t[1]));
|
||||
|
||||
t[0] = readLane(10);
|
||||
t[1] = readLane(11);
|
||||
t[2] = readLane(12);
|
||||
t[3] = readLane(13);
|
||||
t[4] = readLane(14);
|
||||
|
||||
writeLane(10, t[0] ^ ((~t[1]) & t[2]));
|
||||
writeLane(11, t[1] ^ ((~t[2]) & t[3]));
|
||||
writeLane(12, t[2] ^ ((~t[3]) & t[4]));
|
||||
writeLane(13, t[3] ^ ((~t[4]) & t[0]));
|
||||
writeLane(14, t[4] ^ ((~t[0]) & t[1]));
|
||||
|
||||
t[0] = readLane(15);
|
||||
t[1] = readLane(16);
|
||||
t[2] = readLane(17);
|
||||
t[3] = readLane(18);
|
||||
t[4] = readLane(19);
|
||||
|
||||
writeLane(15, t[0] ^ ((~t[1]) & t[2]));
|
||||
writeLane(16, t[1] ^ ((~t[2]) & t[3]));
|
||||
writeLane(17, t[2] ^ ((~t[3]) & t[4]));
|
||||
writeLane(18, t[3] ^ ((~t[4]) & t[0]));
|
||||
writeLane(19, t[4] ^ ((~t[0]) & t[1]));
|
||||
|
||||
t[0] = readLane(20);
|
||||
t[1] = readLane(21);
|
||||
t[2] = readLane(22);
|
||||
t[3] = readLane(23);
|
||||
t[4] = readLane(24);
|
||||
|
||||
writeLane(20, t[0] ^ ((~t[1]) & t[2]));
|
||||
writeLane(21, t[1] ^ ((~t[2]) & t[3]));
|
||||
writeLane(22, t[2] ^ ((~t[3]) & t[4]));
|
||||
writeLane(23, t[3] ^ ((~t[4]) & t[0]));
|
||||
writeLane(24, t[4] ^ ((~t[0]) & t[1]));
|
||||
}
|
||||
|
||||
{ /* ι step (see [Keccak Reference, Section 2.3.5]) */
|
||||
|
||||
XORLane(0, round_constants[round]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(hasher_t, reset, bool,
|
||||
private_sha3_hasher_t *this)
|
||||
{
|
||||
memset(this->state, 0x00, KECCAK_STATE_SIZE);
|
||||
this->rate_index = 0;
|
||||
|
||||
this->keccak->reset(this->keccak);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -388,79 +67,17 @@ METHOD(hasher_t, get_hash_size, size_t,
|
||||
}
|
||||
}
|
||||
|
||||
static void sha3_absorb(private_sha3_hasher_t *this, chunk_t data)
|
||||
{
|
||||
uint64_t *buffer_lanes, *state_lanes;
|
||||
size_t len, rate_lanes;
|
||||
int i;
|
||||
|
||||
buffer_lanes = (uint64_t*)this->rate_buffer;
|
||||
state_lanes = (uint64_t*)this->state;
|
||||
rate_lanes = this->rate / sizeof(uint64_t);
|
||||
|
||||
while (data.len)
|
||||
{
|
||||
len = min(data.len, this->rate - this->rate_index);
|
||||
memcpy(this->rate_buffer + this->rate_index, data.ptr, len);
|
||||
this->rate_index += len;
|
||||
data.ptr += len;
|
||||
data.len -= len;
|
||||
|
||||
if (this->rate_index == this->rate)
|
||||
{
|
||||
for (i = 0; i < rate_lanes; i++)
|
||||
{
|
||||
state_lanes[i] ^= buffer_lanes[i];
|
||||
}
|
||||
this->rate_index = 0;
|
||||
|
||||
keccak_f1600_state_permute(this->state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void sha3_final(private_sha3_hasher_t *this)
|
||||
{
|
||||
uint64_t *buffer_lanes, *state_lanes;
|
||||
size_t rate_lanes, remainder;
|
||||
int i;
|
||||
|
||||
/* Add the delimitedSuffix as the first bit of padding */
|
||||
this->rate_buffer[this->rate_index++] = DELIMITED_SUFFIX;
|
||||
|
||||
buffer_lanes = (uint64_t*)this->rate_buffer;
|
||||
state_lanes = (uint64_t*)this->state;
|
||||
rate_lanes = this->rate_index / sizeof(uint64_t);
|
||||
|
||||
remainder = this->rate_index - rate_lanes * sizeof(uint64_t);
|
||||
if (remainder)
|
||||
{
|
||||
memset(this->rate_buffer + this->rate_index, 0x00,
|
||||
sizeof(uint64_t) - remainder);
|
||||
rate_lanes++;
|
||||
}
|
||||
for (i = 0; i < rate_lanes; i++)
|
||||
{
|
||||
state_lanes[i] ^= buffer_lanes[i];
|
||||
}
|
||||
|
||||
/* Add the second bit of padding */
|
||||
this->state[this->rate - 1] ^= 0x80;
|
||||
|
||||
/* Switch to the squeezing phase */
|
||||
keccak_f1600_state_permute(this->state);
|
||||
}
|
||||
|
||||
METHOD(hasher_t, get_hash, bool,
|
||||
private_sha3_hasher_t *this, chunk_t chunk, uint8_t *buffer)
|
||||
{
|
||||
sha3_absorb(this, chunk);
|
||||
this->keccak->absorb(this->keccak, chunk);
|
||||
|
||||
if (buffer != NULL)
|
||||
{
|
||||
sha3_final(this);
|
||||
memcpy(buffer, this->state, get_hash_size(this));
|
||||
reset(this);
|
||||
this->keccak->finalize(this->keccak);
|
||||
this->keccak->squeeze(this->keccak, get_hash_size(this), buffer);
|
||||
this->keccak->reset(this->keccak);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -470,22 +87,24 @@ METHOD(hasher_t, allocate_hash, bool,
|
||||
{
|
||||
chunk_t allocated_hash;
|
||||
|
||||
sha3_absorb(this, chunk);
|
||||
this->keccak->absorb(this->keccak, chunk);
|
||||
|
||||
if (hash != NULL)
|
||||
{
|
||||
sha3_final(this);
|
||||
this->keccak->finalize(this->keccak);
|
||||
allocated_hash = chunk_alloc(get_hash_size(this));
|
||||
memcpy(allocated_hash.ptr, this->state, allocated_hash.len);
|
||||
reset(this);
|
||||
this->keccak->squeeze(this->keccak, allocated_hash.len,
|
||||
allocated_hash.ptr);
|
||||
this->keccak->reset(this->keccak);
|
||||
*hash = allocated_hash;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(hasher_t, destroy, void,
|
||||
sha3_hasher_t *this)
|
||||
private_sha3_hasher_t *this)
|
||||
{
|
||||
this->keccak->destroy(this->keccak);
|
||||
free(this);
|
||||
}
|
||||
|
||||
@@ -510,18 +129,22 @@ sha3_hasher_t *sha3_hasher_create(hash_algorithm_t algorithm)
|
||||
INIT(this,
|
||||
.public = {
|
||||
.hasher_interface = {
|
||||
.reset = _reset,
|
||||
.get_hash_size = _get_hash_size,
|
||||
.get_hash = _get_hash,
|
||||
.allocate_hash = _allocate_hash,
|
||||
.destroy = _destroy,
|
||||
.reset = _reset,
|
||||
.get_hash_size = _get_hash_size,
|
||||
.get_hash = _get_hash,
|
||||
.allocate_hash = _allocate_hash,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
.algorithm = algorithm,
|
||||
);
|
||||
|
||||
this->rate = KECCAK_STATE_SIZE - 2*get_hash_size(this);
|
||||
reset(this);
|
||||
this->keccak = sha3_keccak_create(2*get_hash_size(this), 0x06);
|
||||
if (!this->keccak)
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,498 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2016 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* Based on the implementation by the Keccak, Keyak and Ketje Teams, namely,
|
||||
* Guido Bertoni, Joan Daemen, Michaël Peeters, Gilles Van Assche and
|
||||
* Ronny Van Keer, hereby denoted as "the implementer".
|
||||
*
|
||||
* To the extent possible under law, the implementer has waived all copyright
|
||||
* and related or neighboring rights to the source code in this file.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "sha3_keccak.h"
|
||||
|
||||
typedef struct private_sha3_keccak_t private_sha3_keccak_t;
|
||||
|
||||
#define KECCAK_STATE_SIZE 200 /* bytes */
|
||||
#define KECCAK_MAX_RATE 168 /* bytes */
|
||||
|
||||
static const uint64_t round_constants[] = {
|
||||
0x0000000000000001ULL,
|
||||
0x0000000000008082ULL,
|
||||
0x800000000000808aULL,
|
||||
0x8000000080008000ULL,
|
||||
0x000000000000808bULL,
|
||||
0x0000000080000001ULL,
|
||||
0x8000000080008081ULL,
|
||||
0x8000000000008009ULL,
|
||||
0x000000000000008aULL,
|
||||
0x0000000000000088ULL,
|
||||
0x0000000080008009ULL,
|
||||
0x000000008000000aULL,
|
||||
0x000000008000808bULL,
|
||||
0x800000000000008bULL,
|
||||
0x8000000000008089ULL,
|
||||
0x8000000000008003ULL,
|
||||
0x8000000000008002ULL,
|
||||
0x8000000000000080ULL,
|
||||
0x000000000000800aULL,
|
||||
0x800000008000000aULL,
|
||||
0x8000000080008081ULL,
|
||||
0x8000000000008080ULL,
|
||||
0x0000000080000001ULL,
|
||||
0x8000000080008008ULL
|
||||
};
|
||||
|
||||
/**
|
||||
* Private data structure with hashing context for SHA-3
|
||||
*/
|
||||
struct private_sha3_keccak_t {
|
||||
|
||||
/**
|
||||
* Public interface for this hasher.
|
||||
*/
|
||||
sha3_keccak_t public;
|
||||
|
||||
/**
|
||||
* Internal state of 1600 bits as defined by FIPS-202
|
||||
*/
|
||||
uint8_t state[KECCAK_STATE_SIZE];
|
||||
|
||||
/**
|
||||
* Rate in bytes
|
||||
*/
|
||||
u_int rate;
|
||||
|
||||
/**
|
||||
* Rate input buffer
|
||||
*/
|
||||
uint8_t rate_buffer[KECCAK_MAX_RATE];
|
||||
|
||||
/**
|
||||
* Index pointing to the current position in the rate buffer
|
||||
*/
|
||||
u_int rate_index;
|
||||
|
||||
/**
|
||||
* Suffix delimiting the input message
|
||||
*/
|
||||
uint8_t delimited_suffix;
|
||||
|
||||
};
|
||||
|
||||
#if BYTE_ORDER != LITTLE_ENDIAN
|
||||
/**
|
||||
* Function to load a 64-bit value using the little-endian (LE) convention.
|
||||
* On a LE platform, this could be greatly simplified using a cast.
|
||||
*/
|
||||
static uint64_t load64(const uint8_t *x)
|
||||
{
|
||||
int i;
|
||||
uint64_t u = 0;
|
||||
|
||||
for (i = 7; i >= 0; --i)
|
||||
{
|
||||
u <<= 8;
|
||||
u |= x[i];
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to store a 64-bit value using the little-endian (LE) convention.
|
||||
* On a LE platform, this could be greatly simplified using a cast.
|
||||
*/
|
||||
static void store64(uint8_t *x, uint64_t u)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
x[i] = u;
|
||||
u >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to XOR into a 64-bit value using the little-endian (LE) convention.
|
||||
* On a LE platform, this could be greatly simplified using a cast.
|
||||
*/
|
||||
static void xor64(uint8_t *x, uint64_t u)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < 8; ++i)
|
||||
{
|
||||
x[i] ^= u;
|
||||
u >>= 8;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Some macros used by the Keccak-f[1600] permutation.
|
||||
*/
|
||||
#define ROL64(a, offset) ((((uint64_t)a) << offset) ^ (((uint64_t)a) >> (64-offset)))
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define readLane(i) (((uint64_t*)state)[i])
|
||||
#define writeLane(i, lane) (((uint64_t*)state)[i]) = (lane)
|
||||
#define XORLane(i, lane) (((uint64_t*)state)[i]) ^= (lane)
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
#define readLane(i) load64((uint8_t*)state+sizeof(uint64_t)*i))
|
||||
#define writeLane(i, lane) store64((uint8_t*)state+sizeof(uint64_t)*i, lane)
|
||||
#define XORLane(i, lane) xor64((uint8_t*)state+sizeof(uint64_t)*i, lane)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Function that computes the Keccak-f[1600] permutation on the given state.
|
||||
*/
|
||||
static void keccak_f1600_state_permute(void *state)
|
||||
{
|
||||
int round;
|
||||
|
||||
for (round = 0; round < 24; round++)
|
||||
{
|
||||
{ /* θ step (see [Keccak Reference, Section 2.3.2]) */
|
||||
|
||||
uint64_t C[5], D;
|
||||
|
||||
/* Compute the parity of the columns */
|
||||
C[0] = readLane(0) ^ readLane( 5) ^ readLane(10)
|
||||
^ readLane(15) ^ readLane(20);
|
||||
C[1] = readLane(1) ^ readLane( 6) ^ readLane(11)
|
||||
^ readLane(16) ^ readLane(21);
|
||||
C[2] = readLane(2) ^ readLane( 7) ^ readLane(12)
|
||||
^ readLane(17) ^ readLane(22);
|
||||
C[3] = readLane(3) ^ readLane( 8) ^ readLane(13)
|
||||
^ readLane(18) ^ readLane(23);
|
||||
C[4] = readLane(4) ^ readLane( 9) ^ readLane(14)
|
||||
^ readLane(19) ^ readLane(24);
|
||||
|
||||
/* Compute and add the θ effect to the whole column */
|
||||
D = C[4] ^ ROL64(C[1], 1);
|
||||
XORLane( 0, D);
|
||||
XORLane( 5, D);
|
||||
XORLane(10, D);
|
||||
XORLane(15, D);
|
||||
XORLane(20, D);
|
||||
|
||||
D = C[0] ^ ROL64(C[2], 1);
|
||||
XORLane( 1, D);
|
||||
XORLane( 6, D);
|
||||
XORLane(11, D);
|
||||
XORLane(16, D);
|
||||
XORLane(21, D);
|
||||
|
||||
D = C[1] ^ ROL64(C[3], 1);
|
||||
XORLane( 2, D);
|
||||
XORLane( 7, D);
|
||||
XORLane(12, D);
|
||||
XORLane(17, D);
|
||||
XORLane(22, D);
|
||||
|
||||
D = C[2] ^ ROL64(C[4], 1);
|
||||
XORLane( 3, D);
|
||||
XORLane( 8, D);
|
||||
XORLane(13, D);
|
||||
XORLane(18, D);
|
||||
XORLane(23, D);
|
||||
|
||||
D = C[3] ^ ROL64(C[0], 1);
|
||||
XORLane( 4, D);
|
||||
XORLane( 9, D);
|
||||
XORLane(14, D);
|
||||
XORLane(19, D);
|
||||
XORLane(24, D);
|
||||
}
|
||||
|
||||
{ /* ρ and π steps (see [Keccak Reference, Sections 2.3.3 and 2.3.4]) */
|
||||
|
||||
uint64_t t1, t2;
|
||||
|
||||
t1 = readLane( 1);
|
||||
|
||||
t2 = readLane(10);
|
||||
writeLane(10, ROL64(t1, 1));
|
||||
|
||||
t1 = readLane( 7);
|
||||
writeLane( 7, ROL64(t2, 3));
|
||||
|
||||
t2 = readLane(11);
|
||||
writeLane(11, ROL64(t1, 6));
|
||||
|
||||
t1 = readLane(17);
|
||||
writeLane(17, ROL64(t2, 10));
|
||||
|
||||
t2 = readLane(18);
|
||||
writeLane(18, ROL64(t1, 15));
|
||||
|
||||
t1 = readLane( 3);
|
||||
writeLane( 3, ROL64(t2, 21));
|
||||
|
||||
t2 = readLane( 5);
|
||||
writeLane( 5, ROL64(t1, 28));
|
||||
|
||||
t1 = readLane(16);
|
||||
writeLane(16, ROL64(t2, 36));
|
||||
|
||||
t2 = readLane( 8);
|
||||
writeLane( 8, ROL64(t1, 45));
|
||||
|
||||
t1 = readLane(21);
|
||||
writeLane(21, ROL64(t2, 55));
|
||||
|
||||
t2 = readLane(24);
|
||||
writeLane(24, ROL64(t1, 2));
|
||||
|
||||
t1 = readLane( 4);
|
||||
writeLane( 4, ROL64(t2, 14));
|
||||
|
||||
t2 = readLane(15);
|
||||
writeLane(15, ROL64(t1, 27));
|
||||
|
||||
t1 = readLane(23);
|
||||
writeLane(23, ROL64(t2, 41));
|
||||
|
||||
t2 = readLane(19);
|
||||
writeLane(19, ROL64(t1, 56));
|
||||
|
||||
t1 = readLane(13);
|
||||
writeLane(13, ROL64(t2, 8));
|
||||
|
||||
t2 = readLane(12);
|
||||
writeLane(12, ROL64(t1, 25));
|
||||
|
||||
t1 = readLane( 2);
|
||||
writeLane( 2, ROL64(t2, 43));
|
||||
|
||||
t2 = readLane(20);
|
||||
writeLane(20, ROL64(t1, 62));
|
||||
|
||||
t1 = readLane(14);
|
||||
writeLane(14, ROL64(t2, 18));
|
||||
|
||||
t2 = readLane(22);
|
||||
writeLane(22, ROL64(t1, 39));
|
||||
|
||||
t1 = readLane( 9);
|
||||
writeLane( 9, ROL64(t2, 61));
|
||||
|
||||
t2 = readLane( 6);
|
||||
writeLane( 6, ROL64(t1, 20));
|
||||
|
||||
writeLane( 1, ROL64(t2, 44));
|
||||
}
|
||||
|
||||
{ /* χ step (see [Keccak Reference, Section 2.3.1]) */
|
||||
|
||||
uint64_t t[5];
|
||||
|
||||
t[0] = readLane(0);
|
||||
t[1] = readLane(1);
|
||||
t[2] = readLane(2);
|
||||
t[3] = readLane(3);
|
||||
t[4] = readLane(4);
|
||||
|
||||
writeLane(0, t[0] ^ ((~t[1]) & t[2]));
|
||||
writeLane(1, t[1] ^ ((~t[2]) & t[3]));
|
||||
writeLane(2, t[2] ^ ((~t[3]) & t[4]));
|
||||
writeLane(3, t[3] ^ ((~t[4]) & t[0]));
|
||||
writeLane(4, t[4] ^ ((~t[0]) & t[1]));
|
||||
|
||||
t[0] = readLane(5);
|
||||
t[1] = readLane(6);
|
||||
t[2] = readLane(7);
|
||||
t[3] = readLane(8);
|
||||
t[4] = readLane(9);
|
||||
|
||||
writeLane(5, t[0] ^ ((~t[1]) & t[2]));
|
||||
writeLane(6, t[1] ^ ((~t[2]) & t[3]));
|
||||
writeLane(7, t[2] ^ ((~t[3]) & t[4]));
|
||||
writeLane(8, t[3] ^ ((~t[4]) & t[0]));
|
||||
writeLane(9, t[4] ^ ((~t[0]) & t[1]));
|
||||
|
||||
t[0] = readLane(10);
|
||||
t[1] = readLane(11);
|
||||
t[2] = readLane(12);
|
||||
t[3] = readLane(13);
|
||||
t[4] = readLane(14);
|
||||
|
||||
writeLane(10, t[0] ^ ((~t[1]) & t[2]));
|
||||
writeLane(11, t[1] ^ ((~t[2]) & t[3]));
|
||||
writeLane(12, t[2] ^ ((~t[3]) & t[4]));
|
||||
writeLane(13, t[3] ^ ((~t[4]) & t[0]));
|
||||
writeLane(14, t[4] ^ ((~t[0]) & t[1]));
|
||||
|
||||
t[0] = readLane(15);
|
||||
t[1] = readLane(16);
|
||||
t[2] = readLane(17);
|
||||
t[3] = readLane(18);
|
||||
t[4] = readLane(19);
|
||||
|
||||
writeLane(15, t[0] ^ ((~t[1]) & t[2]));
|
||||
writeLane(16, t[1] ^ ((~t[2]) & t[3]));
|
||||
writeLane(17, t[2] ^ ((~t[3]) & t[4]));
|
||||
writeLane(18, t[3] ^ ((~t[4]) & t[0]));
|
||||
writeLane(19, t[4] ^ ((~t[0]) & t[1]));
|
||||
|
||||
t[0] = readLane(20);
|
||||
t[1] = readLane(21);
|
||||
t[2] = readLane(22);
|
||||
t[3] = readLane(23);
|
||||
t[4] = readLane(24);
|
||||
|
||||
writeLane(20, t[0] ^ ((~t[1]) & t[2]));
|
||||
writeLane(21, t[1] ^ ((~t[2]) & t[3]));
|
||||
writeLane(22, t[2] ^ ((~t[3]) & t[4]));
|
||||
writeLane(23, t[3] ^ ((~t[4]) & t[0]));
|
||||
writeLane(24, t[4] ^ ((~t[0]) & t[1]));
|
||||
}
|
||||
|
||||
{ /* ι step (see [Keccak Reference, Section 2.3.5]) */
|
||||
|
||||
XORLane(0, round_constants[round]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(sha3_keccak_t, get_rate, u_int,
|
||||
private_sha3_keccak_t *this)
|
||||
{
|
||||
return this->rate;
|
||||
}
|
||||
|
||||
METHOD(sha3_keccak_t, reset, void,
|
||||
private_sha3_keccak_t *this)
|
||||
{
|
||||
memset(this->state, 0x00, KECCAK_STATE_SIZE);
|
||||
this->rate_index = 0;
|
||||
}
|
||||
|
||||
|
||||
METHOD(sha3_keccak_t, absorb, void,
|
||||
private_sha3_keccak_t *this, chunk_t data)
|
||||
{
|
||||
uint64_t *buffer_lanes, *state_lanes;
|
||||
size_t len, rate_lanes;
|
||||
int i;
|
||||
|
||||
buffer_lanes = (uint64_t*)this->rate_buffer;
|
||||
state_lanes = (uint64_t*)this->state;
|
||||
rate_lanes = this->rate / sizeof(uint64_t);
|
||||
|
||||
while (data.len)
|
||||
{
|
||||
len = min(data.len, this->rate - this->rate_index);
|
||||
memcpy(this->rate_buffer + this->rate_index, data.ptr, len);
|
||||
this->rate_index += len;
|
||||
data.ptr += len;
|
||||
data.len -= len;
|
||||
|
||||
if (this->rate_index == this->rate)
|
||||
{
|
||||
for (i = 0; i < rate_lanes; i++)
|
||||
{
|
||||
state_lanes[i] ^= buffer_lanes[i];
|
||||
}
|
||||
this->rate_index = 0;
|
||||
|
||||
keccak_f1600_state_permute(this->state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(sha3_keccak_t, finalize, void,
|
||||
private_sha3_keccak_t *this)
|
||||
{
|
||||
uint64_t *buffer_lanes, *state_lanes;
|
||||
size_t rate_lanes, remainder;
|
||||
int i;
|
||||
|
||||
/* Add the delimitedSuffix as the first bit of padding */
|
||||
this->rate_buffer[this->rate_index++] = this->delimited_suffix;
|
||||
|
||||
buffer_lanes = (uint64_t*)this->rate_buffer;
|
||||
state_lanes = (uint64_t*)this->state;
|
||||
rate_lanes = this->rate_index / sizeof(uint64_t);
|
||||
|
||||
remainder = this->rate_index - rate_lanes * sizeof(uint64_t);
|
||||
if (remainder)
|
||||
{
|
||||
memset(this->rate_buffer + this->rate_index, 0x00,
|
||||
sizeof(uint64_t) - remainder);
|
||||
rate_lanes++;
|
||||
}
|
||||
for (i = 0; i < rate_lanes; i++)
|
||||
{
|
||||
state_lanes[i] ^= buffer_lanes[i];
|
||||
}
|
||||
|
||||
/* Add the second bit of padding */
|
||||
this->state[this->rate - 1] ^= 0x80;
|
||||
|
||||
/* Switch to the squeezing phase */
|
||||
keccak_f1600_state_permute(this->state);
|
||||
this->rate_index = 0;
|
||||
}
|
||||
|
||||
METHOD(sha3_keccak_t, squeeze, void,
|
||||
private_sha3_keccak_t *this, size_t out_len, uint8_t *out)
|
||||
{
|
||||
size_t index = 0, len;
|
||||
|
||||
while (index < out_len)
|
||||
{
|
||||
if (this->rate_index == this->rate)
|
||||
{
|
||||
keccak_f1600_state_permute(this->state);
|
||||
this->rate_index = 0;
|
||||
}
|
||||
len = min(out_len - index, this->rate - this->rate_index);
|
||||
memcpy(out, &this->state[this->rate_index], len);
|
||||
out += len;
|
||||
index += len;
|
||||
this->rate_index += len;
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(sha3_keccak_t, destroy, void,
|
||||
private_sha3_keccak_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
sha3_keccak_t *sha3_keccak_create(u_int capacity, uint8_t delimited_suffix)
|
||||
{
|
||||
private_sha3_keccak_t *this;
|
||||
int rate;
|
||||
|
||||
rate = KECCAK_STATE_SIZE - capacity;
|
||||
|
||||
if (rate <= 0 || rate > KECCAK_MAX_RATE)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_rate = _get_rate,
|
||||
.reset = _reset,
|
||||
.absorb = _absorb,
|
||||
.finalize = _finalize,
|
||||
.squeeze = _squeeze,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.rate = rate,
|
||||
.delimited_suffix = delimited_suffix,
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of 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. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program 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.
|
||||
n */
|
||||
|
||||
/**
|
||||
* @defgroup sha3_keccak sha3_keccak
|
||||
* @{ @ingroup sha3_p
|
||||
*/
|
||||
|
||||
#ifndef SHA3_KECCAK_H_
|
||||
#define SHA3_KECCAK_H_
|
||||
|
||||
typedef struct sha3_keccak_t sha3_keccak_t;
|
||||
|
||||
#include <crypto/hashers/hasher.h>
|
||||
|
||||
/**
|
||||
* Implements the Keccak-f[1600] sponge function as defined by FIPS-202.
|
||||
*/
|
||||
struct sha3_keccak_t {
|
||||
|
||||
/**
|
||||
* Get the available rate in bytes
|
||||
*
|
||||
* @return rate in bytes
|
||||
*/
|
||||
u_int (*get_rate)(sha3_keccak_t *this);
|
||||
|
||||
/**
|
||||
* Resets the interal Keccak state
|
||||
*/
|
||||
void (*reset)(sha3_keccak_t *this);
|
||||
|
||||
/**
|
||||
* Absorbs data into the Keccak state
|
||||
*
|
||||
* @param data data to be absorbed
|
||||
*/
|
||||
void (*absorb)(sha3_keccak_t *this, chunk_t data);
|
||||
|
||||
/**
|
||||
* Finalize the absorbtion phase and switch to the squeeze phase
|
||||
*/
|
||||
void (*finalize)(sha3_keccak_t *this);
|
||||
|
||||
/**
|
||||
* Squeeze the Keccak state to get output data
|
||||
* Can be called multiple times
|
||||
*
|
||||
* @param out_len number of output bytes requested
|
||||
* @param out output buffer, must comprise at least out_len bytes
|
||||
*/
|
||||
void (*squeeze)(sha3_keccak_t *this, size_t out_len, uint8_t *out);
|
||||
|
||||
/**
|
||||
* Destroy the sha3_keccak_t object
|
||||
*/
|
||||
void (*destroy)(sha3_keccak_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new sha3_keccak_t.
|
||||
*
|
||||
* @param capacity required capacity to achieve a given security level
|
||||
* @param delimited_suffix bits delimiting the input message
|
||||
* @return sha3_keccak_t object, NULL if capacity too big
|
||||
*/
|
||||
sha3_keccak_t *sha3_keccak_create(u_int capacity, uint8_t delimited_suffix);
|
||||
|
||||
#endif /** SHA3_KECCAK_H_ @}*/
|
||||
@@ -14,9 +14,10 @@
|
||||
*/
|
||||
|
||||
#include "sha3_plugin.h"
|
||||
#include "sha3_hasher.h"
|
||||
#include "sha3_shake.h"
|
||||
|
||||
#include <library.h>
|
||||
#include "sha3_hasher.h"
|
||||
|
||||
typedef struct private_sha3_plugin_t private_sha3_plugin_t;
|
||||
|
||||
@@ -46,6 +47,9 @@ METHOD(plugin_t, get_features, int,
|
||||
PLUGIN_PROVIDE(HASHER, HASH_SHA3_256),
|
||||
PLUGIN_PROVIDE(HASHER, HASH_SHA3_384),
|
||||
PLUGIN_PROVIDE(HASHER, HASH_SHA3_512),
|
||||
PLUGIN_REGISTER(XOF, sha3_shake_create),
|
||||
PLUGIN_PROVIDE(XOF, XOF_SHAKE_128),
|
||||
PLUGIN_PROVIDE(XOF, XOF_SHAKE_256),
|
||||
};
|
||||
*features = f;
|
||||
return countof(f);
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of 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. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#include "sha3_shake.h"
|
||||
#include "sha3_keccak.h"
|
||||
|
||||
typedef struct private_sha3_shake_t private_sha3_shake_t;
|
||||
|
||||
|
||||
/**
|
||||
* Private data structure with hashing context for SHA-3
|
||||
*/
|
||||
struct private_sha3_shake_t {
|
||||
|
||||
/**
|
||||
* Public interface for this hasher.
|
||||
*/
|
||||
sha3_shake_t public;
|
||||
|
||||
/**
|
||||
* XOF algorithm to be used (XOF_SHAKE_128 or XOF_SHAKE_256)
|
||||
*/
|
||||
ext_out_function_t algorithm;
|
||||
|
||||
/**
|
||||
* SHA-3 Keccak state
|
||||
*/
|
||||
sha3_keccak_t *keccak;
|
||||
|
||||
/**
|
||||
* Capacity in bytes of the SHA-3 Keccak state
|
||||
*/
|
||||
u_int capacity;
|
||||
|
||||
};
|
||||
|
||||
|
||||
METHOD(xof_t, get_bytes, bool,
|
||||
private_sha3_shake_t *this, size_t out_len, uint8_t *buffer)
|
||||
{
|
||||
this->keccak->squeeze(this->keccak, out_len, buffer);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(xof_t, allocate_bytes, bool,
|
||||
private_sha3_shake_t *this, size_t out_len, chunk_t *chunk)
|
||||
{
|
||||
*chunk = chunk_alloc(out_len);
|
||||
this->keccak->squeeze(this->keccak, out_len, chunk->ptr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(xof_t, get_block_size, size_t,
|
||||
private_sha3_shake_t *this)
|
||||
{
|
||||
return this->keccak->get_rate(this->keccak);
|
||||
}
|
||||
|
||||
METHOD(xof_t, get_seed_size, size_t,
|
||||
private_sha3_shake_t *this)
|
||||
{
|
||||
return this->capacity;
|
||||
}
|
||||
|
||||
METHOD(xof_t, set_seed, bool,
|
||||
private_sha3_shake_t *this, chunk_t seed)
|
||||
{
|
||||
this->keccak->reset(this->keccak);
|
||||
this->keccak->absorb(this->keccak, seed);
|
||||
this->keccak->finalize(this->keccak);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
METHOD(xof_t, destroy, void,
|
||||
private_sha3_shake_t *this)
|
||||
{
|
||||
this->keccak->destroy(this->keccak);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
sha3_shake_t* sha3_shake_create(ext_out_function_t algorithm)
|
||||
{
|
||||
private_sha3_shake_t *this;
|
||||
u_int capacity = 0;
|
||||
|
||||
switch (algorithm)
|
||||
{
|
||||
case XOF_SHAKE_128:
|
||||
capacity = 32;
|
||||
break;
|
||||
case XOF_SHAKE_256:
|
||||
capacity = 64;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.xof_interface = {
|
||||
.get_bytes = _get_bytes,
|
||||
.allocate_bytes = _allocate_bytes,
|
||||
.get_block_size = _get_block_size,
|
||||
.get_seed_size = _get_seed_size,
|
||||
.set_seed = _set_seed,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
.algorithm = algorithm,
|
||||
.capacity = capacity,
|
||||
);
|
||||
|
||||
this->keccak = sha3_keccak_create(capacity, 0x1f);
|
||||
if (!this->keccak)
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of 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. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup sha3_shake sha3_shake
|
||||
* @{ @ingroup sha3_p
|
||||
*/
|
||||
|
||||
#ifndef SHA3_SHAKE_H_
|
||||
#define SHA3_SHAKE_H_
|
||||
|
||||
typedef struct sha3_shake_t sha3_shake_t;
|
||||
|
||||
#include <crypto/xofs/xof.h>
|
||||
|
||||
/**
|
||||
* Implementation of xof_t interface using the SHA-3 XOF algorithm family
|
||||
* SHAKE128 and SHAKE256 as defined by FIPS-202.
|
||||
*/
|
||||
struct sha3_shake_t {
|
||||
|
||||
/**
|
||||
* Generic xof_t interface for this Extended Output Function (XOF).
|
||||
*/
|
||||
xof_t xof_interface;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new sha3_shake_t.
|
||||
*
|
||||
* @param algorithm XOF_SHAKE_128 or XOF_SHAKE_256
|
||||
* @return sha3_shake_t object, NULL if not supported
|
||||
*/
|
||||
sha3_shake_t* sha3_shake_create(ext_out_function_t algorithm);
|
||||
|
||||
#endif /** SHA3_SHAKE_H_ @}*/
|
||||
Reference in New Issue
Block a user