Skip to content
Snippets Groups Projects
Commit 792137f8 authored by Mathias Tausig's avatar Mathias Tausig
Browse files

hashes:sha3: Integrate SHA-3 into RIOT API

Add init/update/final interface
Add interface functions for direct SHA3
Add unit tests for SHA-3
Document functions and types
Reduced var scope in Keccak code
Add CCO Copyright notice to Keccak code
parent a44a313e
No related branches found
No related tags found
No related merge requests found
/*
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".
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".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
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/
*/
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/
RIOT OS adaptations by Mathias Tausig
This software is released under the Creative Commons CC0 1.0 license.
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
For more information see: http://creativecommons.org/publicdomain/zero/1.0/
*/
/*
================================================================
The purpose of this source file is to demonstrate a readable and compact
implementation of all the Keccak instances approved in the FIPS 202 standard,
including the hash functions and the extendable-output functions (XOFs).
We focused on clarity and on source-code compactness,
rather than on the performance.
The advantages of this implementation are:
+ The source code is compact, after removing the comments, that is. :-)
+ There are no tables with arbitrary constants.
+ For clarity, the comments link the operations to the specifications using
================================================================
The purpose of this source file is to demonstrate a readable and compact
implementation of all the Keccak instances approved in the FIPS 202 standard,
including the hash functions and the extendable-output functions (XOFs).
We focused on clarity and on source-code compactness,
rather than on the performance.
The advantages of this implementation are:
+ The source code is compact, after removing the comments, that is. :-)
+ There are no tables with arbitrary constants.
+ For clarity, the comments link the operations to the specifications using
the same notation as much as possible.
+ There is no restriction in cryptographic features. In particular,
+ There is no restriction in cryptographic features. In particular,
the SHAKE128 and SHAKE256 XOFs can produce any output length.
+ The code does not use much RAM, as all operations are done in place.
+ The code does not use much RAM, as all operations are done in place.
The drawbacks of this implementation are:
The drawbacks of this implementation are:
- There is no message queue. The whole message must be ready in a buffer.
- It is not optimized for peformance.
The implementation is even simpler on a little endian platform. Just define the
LITTLE_ENDIAN symbol in that case.
The implementation is even simpler on a little endian platform. Just define the
LITTLE_ENDIAN symbol in that case.
For a more complete set of implementations, please refer to
the Keccak Code Package at https://github.com/gvanas/KeccakCodePackage
For a more complete set of implementations, please refer to
the Keccak Code Package at https://github.com/gvanas/KeccakCodePackage
For more information, please refer to:
* [Keccak Reference] http://keccak.noekeon.org/Keccak-reference-3.0.pdf
* [Keccak Specifications Summary] http://keccak.noekeon.org/specs_summary.html
For more information, please refer to:
* [Keccak Reference] http://keccak.noekeon.org/Keccak-reference-3.0.pdf
* [Keccak Specifications Summary] http://keccak.noekeon.org/specs_summary.html
This file uses UTF-8 encoding, as some comments use Greek letters.
================================================================
*/
This file uses UTF-8 encoding, as some comments use Greek letters.
================================================================
*/
#include <hashes/sha3.h>
/**
* Function to compute the Keccak[r, c] sponge function over a given input.
* @param rate The value of the rate r.
* @param capacity The value of the capacity c.
* @param input Pointer to the input message.
* @param inputByteLen The number of input bytes provided in the input message.
* @param delimitedSuffix Bits that will be automatically appended to the end
* of the input message, as in domain separation.
* This is a byte containing from 0 to 7 bits
* These <i>n</i> bits must be in the least significant bit positions
* and must be delimited with a bit 1 at position <i>n</i>
* (counting from 0=LSB to 7=MSB) and followed by bits 0
* from position <i>n</i>+1 to position 7.
* Some examples:
* - If no bits are to be appended, then @a delimitedSuffix must be 0x01.
* - If the 2-bit sequence 0,1 is to be appended (as for SHA3-*), @a delimitedSuffix must be 0x06.
* - If the 4-bit sequence 1,1,1,1 is to be appended (as for SHAKE*), @a delimitedSuffix must be 0x1F.
* - If the 7-bit sequence 1,1,0,1,0,0,0 is to be absorbed, @a delimitedSuffix must be 0x8B.
* @param output Pointer to the buffer where to store the output.
* @param outputByteLen The number of output bytes desired.
* @pre One must have r+c=1600 and the rate a multiple of 8 bits in this implementation.
*/
void Keccak(unsigned int rate, unsigned int capacity, const unsigned char *input, unsigned long long int inputByteLen, unsigned char delimitedSuffix, unsigned char *output, unsigned long long int outputByteLen);
* Function to compute the Keccak[r, c] sponge function over a given input.
* @param rate The value of the rate r.
* @param capacity The value of the capacity c.
* @param input Pointer to the input message.
* @param inputByteLen The number of input bytes provided in the input message.
* @param delimitedSuffix Bits that will be automatically appended to the end
* of the input message, as in domain separation.
* This is a byte containing from 0 to 7 bits
* These <i>n</i> bits must be in the least significant bit positions
* and must be delimited with a bit 1 at position <i>n</i>
* (counting from 0=LSB to 7=MSB) and followed by bits 0
* from position <i>n</i>+1 to position 7.
* Some examples:
* - If no bits are to be appended, then @a delimitedSuffix must be 0x01.
* - If the 2-bit sequence 0,1 is to be appended (as for SHA3-*),
* @a delimitedSuffix must be 0x06.
* - If the 4-bit sequence 1,1,1,1 is to be appended (as for SHAKE*),
* @a delimitedSuffix must be 0x1F.
* - If the 7-bit sequence 1,1,0,1,0,0,0 is to be absorbed,
* @a delimitedSuffix must be 0x8B.
* @param output Pointer to the buffer where to store the output.
* @param outputByteLen The number of output bytes desired.
* @pre One must have r+c=1600 and the rate a multiple of 8 bits in this implementation.
*/
static void Keccak(unsigned int rate, unsigned int capacity, const unsigned char *input,
unsigned long long int inputByteLen, unsigned char delimitedSuffix, unsigned char *output,
unsigned long long int outputByteLen);
/**
* Function to compute SHAKE128 on the input message with any output length.
*/
* Function to compute SHAKE128 on the input message with any output length.
*/
void FIPS202_SHAKE128(const unsigned char *input, unsigned int inputByteLen, unsigned char *output, int outputByteLen)
{
Keccak(1344, 256, input, inputByteLen, 0x1F, output, outputByteLen);
}
/**
* Function to compute SHAKE256 on the input message with any output length.
*/
* Function to compute SHAKE256 on the input message with any output length.
*/
void FIPS202_SHAKE256(const unsigned char *input, unsigned int inputByteLen, unsigned char *output, int outputByteLen)
{
Keccak(1088, 512, input, inputByteLen, 0x1F, output, outputByteLen);
}
/**
* Function to compute SHA3-224 on the input message. The output length is fixed to 28 bytes.
*/
* Function to compute SHA3-224 on the input message. The output length is fixed to 28 bytes.
*/
void FIPS202_SHA3_224(const unsigned char *input, unsigned int inputByteLen, unsigned char *output)
{
Keccak(1152, 448, input, inputByteLen, 0x06, output, 28);
}
/**
* Function to compute SHA3-256 on the input message. The output length is fixed to 32 bytes.
*/
void FIPS202_SHA3_256(const unsigned char *input, unsigned int inputByteLen, unsigned char *output)
* Function to compute SHA3-256 on the input message. The output length is fixed to 32 bytes.
*/
static void FIPS202_SHA3_256(const unsigned char *input, unsigned int inputByteLen, unsigned char *output)
{
Keccak(1088, 512, input, inputByteLen, 0x06, output, SHA3_256_DIGEST_LENGTH);
}
void sha3_256(void *digest, const void *data, size_t len)
{
FIPS202_SHA3_256(data, len, digest);
}
void sha3_256_init(keccak_state_t *ctx)
{
Keccak_init(ctx, 1088, 512, 0x06);
}
void sha3_update(keccak_state_t *ctx, const void *data, size_t len)
{
Keccak_update(ctx, data, len);
}
void sha3_256_final(keccak_state_t *ctx, void *digest)
{
Keccak(1088, 512, input, inputByteLen, 0x06, output, 32);
Keccak_final(ctx, digest, SHA3_256_DIGEST_LENGTH);
}
/**
* Function to compute SHA3-384 on the input message. The output length is fixed to 48 bytes.
*/
void FIPS202_SHA3_384(const unsigned char *input, unsigned int inputByteLen, unsigned char *output)
* Function to compute SHA3-384 on the input message. The output length is fixed to 48 bytes.
*/
static void FIPS202_SHA3_384(const unsigned char *input, unsigned int inputByteLen, unsigned char *output)
{
Keccak(832, 768, input, inputByteLen, 0x06, output, 48);
}
void sha3_384(void *digest, const void *data, size_t len)
{
FIPS202_SHA3_384(data, len, digest);
}
void sha3_384_init(keccak_state_t *ctx)
{
Keccak_init(ctx, 832, 768, 0x06);
}
void sha3_384_final(keccak_state_t *ctx, void *digest)
{
Keccak_final(ctx, digest, SHA3_384_DIGEST_LENGTH);
}
/**
* Function to compute SHA3-512 on the input message. The output length is fixed to 64 bytes.
*/
void FIPS202_SHA3_512(const unsigned char *input, unsigned int inputByteLen, unsigned char *output)
* Function to compute SHA3-512 on the input message. The output length is fixed to 64 bytes.
*/
static void FIPS202_SHA3_512(const unsigned char *input, unsigned int inputByteLen, unsigned char *output)
{
Keccak(576, 1024, input, inputByteLen, 0x06, output, 64);
}
void sha3_512(void *digest, const void *data, size_t len)
{
FIPS202_SHA3_512(data, len, digest);
}
void sha3_512_init(keccak_state_t *ctx)
{
Keccak_init(ctx, 576, 1024, 0x06);
}
void sha3_512_final(keccak_state_t *ctx, void *digest)
{
Keccak_final(ctx, digest, SHA3_512_DIGEST_LENGTH);
}
/*
================================================================
Technicalities
================================================================
*/
================================================================
Technicalities
================================================================
*/
typedef unsigned char UINT8;
typedef unsigned long long int UINT64;
......@@ -133,14 +199,14 @@ typedef UINT64 tKeccakLane;
#ifndef 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.
*/
* On a LE platform, this could be greatly simplified using a cast.
*/
static UINT64 load64(const UINT8 *x)
{
int i;
UINT64 u=0;
UINT64 u = 0;
for(i=7; i>=0; --i) {
for (i = 7; i >= 0; --i) {
u <<= 8;
u |= x[i];
}
......@@ -148,26 +214,26 @@ static UINT64 load64(const UINT8 *x)
}
/** 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.
*/
* On a LE platform, this could be greatly simplified using a cast.
*/
static void store64(UINT8 *x, UINT64 u)
{
unsigned int i;
for(i=0; i<8; ++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.
*/
* On a LE platform, this could be greatly simplified using a cast.
*/
static void xor64(UINT8 *x, UINT64 u)
{
unsigned int i;
for(i=0; i<8; ++i) {
for (i = 0; i < 8; ++i) {
x[i] ^= u;
u >>= 8;
}
......@@ -175,76 +241,80 @@ static void xor64(UINT8 *x, UINT64 u)
#endif
/*
================================================================
A readable and compact implementation of the Keccak-f[1600] permutation.
================================================================
*/
================================================================
A readable and compact implementation of the Keccak-f[1600] permutation.
================================================================
*/
#define ROL64(a, offset) ((((UINT64)a) << offset) ^ (((UINT64)a) >> (64-offset)))
#define i(x, y) ((x)+5*(y))
#define ROL64(a, offset) ((((UINT64)a) << offset) ^ (((UINT64)a) >> (64 - offset)))
#define i(x, y) ((x) + 5 * (y))
#ifdef LITTLE_ENDIAN
#define readLane(x, y) (((tKeccakLane*)state)[i(x, y)])
#define writeLane(x, y, lane) (((tKeccakLane*)state)[i(x, y)]) = (lane)
#define XORLane(x, y, lane) (((tKeccakLane*)state)[i(x, y)]) ^= (lane)
#define readLane(x, y) (((tKeccakLane *)state)[i(x, y)])
#define writeLane(x, y, lane) (((tKeccakLane *)state)[i(x, y)]) = (lane)
#define XORLane(x, y, lane) (((tKeccakLane *)state)[i(x, y)]) ^= (lane)
#else
#define readLane(x, y) load64((UINT8*)state+sizeof(tKeccakLane)*i(x, y))
#define writeLane(x, y, lane) store64((UINT8*)state+sizeof(tKeccakLane)*i(x, y), lane)
#define XORLane(x, y, lane) xor64((UINT8*)state+sizeof(tKeccakLane)*i(x, y), lane)
#define readLane(x, y) load64((UINT8 *)state + sizeof(tKeccakLane) * i(x, y))
#define writeLane(x, y, lane) store64((UINT8 *)state + sizeof(tKeccakLane) * i(x, y), lane)
#define XORLane(x, y, lane) xor64((UINT8 *)state + sizeof(tKeccakLane) * i(x, y), lane)
#endif
/**
* Function that computes the linear feedback shift register (LFSR) used to
* define the round constants (see [Keccak Reference, Section 1.2]).
*/
int LFSR86540(UINT8 *LFSR)
* Function that computes the linear feedback shift register (LFSR) used to
* define the round constants (see [Keccak Reference, Section 1.2]).
*/
static int LFSR86540(UINT8 *LFSR)
{
int result = ((*LFSR) & 0x01) != 0;
if (((*LFSR) & 0x80) != 0)
if (((*LFSR) & 0x80) != 0) {
/* Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1 */
(*LFSR) = ((*LFSR) << 1) ^ 0x71;
else
}
else {
(*LFSR) <<= 1;
}
return result;
}
/**
* Function that computes the Keccak-f[1600] permutation on the given state.
*/
void KeccakF1600_StatePermute(void *state)
static void KeccakF1600_StatePermute(void *state)
{
unsigned int round, x, y, j, t;
UINT8 LFSRstate = 0x01;
for(round=0; round<24; round++) {
for (round = 0; round < 24; round++) {
{ /* === θ step (see [Keccak Reference, Section 2.3.2]) === */
tKeccakLane C[5], D;
tKeccakLane C[5];
/* Compute the parity of the columns */
for(x=0; x<5; x++)
C[x] = readLane(x, 0) ^ readLane(x, 1) ^ readLane(x, 2) ^ readLane(x, 3) ^ readLane(x, 4);
for(x=0; x<5; x++) {
for (x = 0; x < 5; x++)
C[x] = readLane(x, 0) ^ readLane(x, 1) ^ readLane(x, 2) ^ readLane(x, 3) ^
readLane(x, 4);
for (x = 0; x < 5; x++) {
/* Compute the θ effect for a given column */
D = C[(x+4)%5] ^ ROL64(C[(x+1)%5], 1);
tKeccakLane D = C[(x + 4) % 5] ^ ROL64(C[(x + 1) % 5], 1);
/* Add the θ effect to the whole column */
for (y=0; y<5; y++)
for (y = 0; y < 5; y++)
XORLane(x, y, D);
}
}
{ /* === ρ and π steps (see [Keccak Reference, Sections 2.3.3 and 2.3.4]) === */
tKeccakLane current, temp;
tKeccakLane current;
/* Start at coordinates (1 0) */
x = 1; y = 0;
current = readLane(x, y);
/* Iterate over ((0 1)(2 3))^t * (1 0) for 0 ≤ t ≤ 23 */
for(t=0; t<24; t++) {
for (t = 0; t < 24; t++) {
/* Compute the rotation constant r = (t+1)(t+2)/2 */
unsigned int r = ((t+1)*(t+2)/2)%64;
unsigned int r = ((t + 1) * (t + 2) / 2) % 64;
/* Compute ((0 1)(2 3)) * (x y) */
unsigned int Y = (2*x+3*y)%5; x = y; y = Y;
unsigned int Y = (2 * x + 3 * y) % 5; x = y; y = Y;
/* Swap current and state(x,y), and rotate */
temp = readLane(x, y);
tKeccakLane temp = readLane(x, y);
writeLane(x, y, ROL64(current, r));
current = temp;
}
......@@ -252,53 +322,58 @@ void KeccakF1600_StatePermute(void *state)
{ /* === χ step (see [Keccak Reference, Section 2.3.1]) === */
tKeccakLane temp[5];
for(y=0; y<5; y++) {
for (y = 0; y < 5; y++) {
/* Take a copy of the plane */
for(x=0; x<5; x++)
for (x = 0; x < 5; x++)
temp[x] = readLane(x, y);
/* Compute χ on the plane */
for(x=0; x<5; x++)
writeLane(x, y, temp[x] ^((~temp[(x+1)%5]) & temp[(x+2)%5]));
for (x = 0; x < 5; x++)
writeLane(x, y, temp[x] ^ ((~temp[(x + 1) % 5]) & temp[(x + 2) % 5]));
}
}
{ /* === ι step (see [Keccak Reference, Section 2.3.5]) === */
for(j=0; j<7; j++) {
unsigned int bitPosition = (1<<j)-1; /* 2^j-1 */
if (LFSR86540(&LFSRstate))
XORLane(0, 0, (tKeccakLane)1<<bitPosition);
{
/* === ι step (see [Keccak Reference, Section 2.3.5]) === */
for (j = 0; j < 7; j++) {
unsigned int bitPosition = (1 << j) - 1; /* 2^j-1 */
if (LFSR86540(&LFSRstate)) {
XORLane(0, 0, (tKeccakLane)1 << bitPosition);
}
}
}
}
}
/*
================================================================
A readable and compact implementation of the Keccak sponge functions
that use the Keccak-f[1600] permutation.
================================================================
*/
================================================================
A readable and compact implementation of the Keccak sponge functions
that use the Keccak-f[1600] permutation.
================================================================
*/
#include <string.h>
#define MIN(a, b) ((a) < (b) ? (a) : (b))
void Keccak(unsigned int rate, unsigned int capacity, const unsigned char *input, unsigned long long int inputByteLen, unsigned char delimitedSuffix, unsigned char *output, unsigned long long int outputByteLen)
static void Keccak(unsigned int rate, unsigned int capacity, const unsigned char *input,
unsigned long long int inputByteLen, unsigned char delimitedSuffix,
unsigned char *output, unsigned long long int outputByteLen)
{
UINT8 state[200];
unsigned int rateInBytes = rate/8;
unsigned int rateInBytes = rate / 8;
unsigned int blockSize = 0;
unsigned int i;
if (((rate + capacity) != 1600) || ((rate % 8) != 0))
if (((rate + capacity) != 1600) || ((rate % 8) != 0)) {
return;
}
/* === Initialize the state === */
memset(state, 0, sizeof(state));
/* === Absorb all the input blocks === */
while(inputByteLen > 0) {
while (inputByteLen > 0) {
blockSize = MIN(inputByteLen, rateInBytes);
for(i=0; i<blockSize; i++)
for (i = 0; i < blockSize; i++)
state[i] ^= input[i];
input += blockSize;
inputByteLen -= blockSize;
......@@ -310,24 +385,97 @@ void Keccak(unsigned int rate, unsigned int capacity, const unsigned char *input
}
/* === Do the padding and switch to the squeezing phase === */
/* Absorb the last few bits and add the first bit of padding (which coincides with the delimiter in delimitedSuffix) */
/* Absorb the last few bits and add the first bit of padding (which coincides with the
delimiter in delimitedSuffix) */
state[blockSize] ^= delimitedSuffix;
/* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */
if (((delimitedSuffix & 0x80) != 0) && (blockSize == (rateInBytes-1)))
/* If the first bit of padding is at position rate-1, we need a whole new block for the
second bit of padding */
if (((delimitedSuffix & 0x80) != 0) && (blockSize == (rateInBytes - 1))) {
KeccakF1600_StatePermute(state);
}
/* Add the second bit of padding */
state[rateInBytes-1] ^= 0x80;
state[rateInBytes - 1] ^= 0x80;
/* Switch to the squeezing phase */
KeccakF1600_StatePermute(state);
/* === Squeeze out all the output blocks === */
while(outputByteLen > 0) {
while (outputByteLen > 0) {
blockSize = MIN(outputByteLen, rateInBytes);
memcpy(output, state, blockSize);
output += blockSize;
outputByteLen -= blockSize;
if (outputByteLen > 0)
if (outputByteLen > 0) {
KeccakF1600_StatePermute(state);
}
}
}
void Keccak_init(keccak_state_t *ctx, unsigned int rate, unsigned int capacity,
unsigned char delimitedSuffix)
{
ctx->rateInBytes = rate / 8;
if (((rate + capacity) != 1600) || ((rate % 8) != 0)) {
return;
}
/* === Initialize the state === */
memset(ctx->state, 0, sizeof(ctx->state));
ctx->i = 0;
ctx->rate = rate;
ctx->capacity = capacity;
ctx->delimitedSuffix = delimitedSuffix;
}
void Keccak_update(keccak_state_t *ctx, const unsigned char *input,
unsigned long long int inputByteLen)
{
/* === Absorb all the input blocks === */
while (inputByteLen > 0) {
unsigned int blockSize = MIN(inputByteLen + ctx->i, ctx->rateInBytes);
while (ctx->i < blockSize) {
ctx->state[ctx->i] ^= *input;
++(ctx->i);
input++;
--inputByteLen;
}
if (blockSize == ctx->rateInBytes) {
KeccakF1600_StatePermute(ctx->state);
blockSize = 0;
ctx->i = 0;
}
}
}
void Keccak_final(keccak_state_t *ctx, unsigned char *output, unsigned long long int outputByteLen)
{
/* === Do the padding and switch to the squeezing phase === */
/* Absorb the last few bits and add the first bit of padding (which coincides with the
delimiter in delimitedSuffix) */
ctx->state[ctx->i] ^= ctx->delimitedSuffix;
/* If the first bit of padding is at position rate-1, we need a whole new block for the
second bit of padding */
if (((ctx->delimitedSuffix & 0x80) != 0) && (ctx->i == (ctx->rateInBytes - 1))) {
KeccakF1600_StatePermute(ctx->state);
}
/* Add the second bit of padding */
ctx->state[ctx->rateInBytes - 1] ^= 0x80;
/* Switch to the squeezing phase */
KeccakF1600_StatePermute(ctx->state);
/* === Squeeze out all the output blocks === */
while (outputByteLen > 0) {
unsigned int blockSize = MIN(outputByteLen, ctx->rateInBytes);
memcpy(output, ctx->state, blockSize);
output += blockSize;
outputByteLen -= blockSize;
if (outputByteLen > 0) {
KeccakF1600_StatePermute(ctx->state);
}
}
}
/*-
* 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".
*
* RIOT-OS adaptaion by Mathias Tausig
*
* This software is released under the Creative Commons CC0 1.0 license.
* To the extent possible under law, the implementer has waived all copyright
* and related or neighboring rights to the source code in this file.
* For more information see: http://creativecommons.org/publicdomain/zero/1.0/
*/
/**
* @ingroup sys_hashes
* @{
*
* @file
* @brief Header definitions for the SHA-3 hash function
*
* @author Implementation by the Keccak, Keyak and Ketje Teams (https://keccak.team/)
* @author RIOT OS adaptations by Mathias Tausig
*/
#ifndef HASHES_SHA3_H
#define HASHES_SHA3_H
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SHA3_256_DIGEST_LENGTH 32
#define SHA3_384_DIGEST_LENGTH 48
#define SHA3_512_DIGEST_LENGTH 64
/**
* @brief Context for operations on a sponge with keccak permutation
*/
typedef struct {
/** State of the Keccak sponge */
unsigned char state[200];
/** Current position within the state */
unsigned int i;
/** The suffix used for padding */
unsigned char delimitedSuffix;
/** The bitrate of the sponge */
unsigned int rate;
/** The capacity in bits of the sponge */
unsigned int capacity;
/** The rate in bytes of the sponge */
unsigned int rateInBytes;
} keccak_state_t;
/**
* @brief Initialise a sponge based on a keccak-1600 permutation
*
* @param[out] ctx context handle to initialise
* @param[in] rate the desired rate of the sponge
* @param[in] capacity the desired capcity of the sponge
* @param[in] delimitedSuffix suffix to be appended to the message after the absorbation phase
*/
void Keccak_init(keccak_state_t *ctx, unsigned int rate, unsigned int capacity,
unsigned char delimitedSuffix);
/**
* @brief Absorbs data into a sponge. Can be called multiple times
*
* @param[in,out] ctx context handle of the sponge
* @param[in] input pointer to the data to be absorbed
* @param[in] inputByteLen length of the input data in bytes
*/
void Keccak_update(keccak_state_t *ctx, const unsigned char *input,
unsigned long long int inputByteLen);
/**
* @brief Squeeze data from a sponge
*
* @param[in,out] ctx context handle of the sponge
* @param[out] output the squeezed data
* @param[in] outputByteLen size of the data to be squeezed.
*/
void Keccak_final(keccak_state_t *ctx, unsigned char *output,
unsigned long long int outputByteLen);
/**
* @brief SHA-3-256 initialization. Begins a SHA-3-256 operation.
*
* @param[in] ctx keccak_state_t handle to initialise
*/
void sha3_256_init(keccak_state_t *ctx);
/**
* @brief Add bytes into the hash
*
* @param[in,out] ctx context handle to use
* @param[in] data Input data
* @param[in] len Length of @p data
*/
void sha3_update(keccak_state_t *ctx, const void *data, size_t len);
/**
* @brief SHA-3-256 finalization. Pads the input data and exports the hash value
*
* @param[in,out] ctx context handle to use
* @param[out] digest resulting digest, this is the hash of all the bytes
*/
void sha3_256_final(keccak_state_t *ctx, void *digest);
/**
* @brief SHA-3-384 initialization. Begins a SHA-3-256 operation.
*
* @param[in] ctx keccak_state_t handle to initialise
*/
void sha3_384_init(keccak_state_t *ctx);
/**
* @brief SHA-3-384 finalization. Pads the input data and exports the hash value
*
* @param[in,out] ctx context handle to use
* @param[out] digest resulting digest, this is the hash of all the bytes
*/
void sha3_384_final(keccak_state_t *ctx, void *digest);
/**
* @brief SHA-3-512 initialization. Begins a SHA-3-256 operation.
*
* @param[in] ctx keccak_state_t handle to initialise
*/
void sha3_512_init(keccak_state_t *ctx);
/**
* @brief SHA-3-512 finalization. Pads the input data and exports the hash value
*
* @param[in,out] ctx context handle to use
* @param[out] digest resulting digest, this is the hash of all the bytes
*/
void sha3_512_final(keccak_state_t *ctx, void *digest);
/**
* @brief A wrapper function to simplify the generation of a hash, this is
* usefull for generating SHA-3-256 from one buffer
*
* @param[in] data pointer to the buffer to generate hash from
* @param[in] len length of the buffer
* @param[out] digest pointer to an array for the result, length must
* be SHA3_256_DIGEST_LENGTH
*/
void sha3_256(void *digest, const void *data, size_t len);
/**
* @brief A wrapper function to simplify the generation of a hash, this is
* usefull for generating SHA-3-384 from one buffer
*
* @param[in] data pointer to the buffer to generate hash from
* @param[in] len length of the buffer
* @param[out] digest pointer to an array for the result, length must
* be SHA3_384_DIGEST_LENGTH
*/
void sha3_384(void *digest, const void *data, size_t len);
/**
* @brief A wrapper function to simplify the generation of a hash, this is
* usefull for generating SHA-3-512 from one buffer
*
* @param[in] data pointer to the buffer to generate hash from
* @param[in] len length of the buffer
* @param[out] digest pointer to an array for the result, length must
* be SHA3_512_DIGEST_LENGTH
*/
void sha3_512(void *digest, const void *data, size_t len);
#ifdef __cplusplus
}
#endif
#endif /* HASHES_SHA3_H */
/** @} */
/*
* Copyright (C) 2017-2018 Mathias Tausig <mathias.tausig@fh-campsuwien.ac.at>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup unittests
* @{
*
* @file
* @brief Test cases for the SHA-3 hash implementation
*
* @author Mathias Tausig <mathias.tausig@fh-campsuwien.ac.at>
*
* @}
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "hashes/sha3.h"
#include "embUnit/embUnit.h"
/**
* @brief expected SHA3-256 hash for test 01
*
* All test values taken from the Keccak code pacakge:
* https://github.com/gvanas/KeccakCodePackage
* Files: TestVectors/ShortMsgKAT_SHA3-256.txt, TestVectors/ShortMsgKAT_SHA3-384.txt,
* TestVectors/ShortMsgKAT_SHA3-512.txt
*
* * converted using:
* s=$(echo '<hash string>' | sed -e 's/../0x&, /g' | sed 's/, $//'); echo {$s}\;
*
* where <hash string> is the above sequence of characters A7...4A
*
* msg = ''
* md_256 = A7FFC6F8BF1ED76651C14756A061D662F580FF4DE43B49FA82D80A4B80F8434A
* md_384 = 0C63A75B845E4F7D01107D852E4C2485C51A50AAAA94FC61995E71BBEE983A2A
* C3713831264ADB47FB6BD1E058D5F004
* md_512 = A69F73CCA23A9AC5C8B567DC185A756E97C982164FE25859E0D1DCC1475C80A6
* 15B2123AF1F5F94C11E3E9402C3AC558F500199D95B6D3E301758586281DCD26
*
*/
static const uint8_t m01[1];
size_t m01_len = 0;
static const uint8_t m01_1[1];
size_t m01_1_len = 0;
static const uint8_t m01_2[1];
size_t m01_2_len = 0;
static const uint8_t h01_256[] = { 0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66,
0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62,
0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA,
0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A };
static const uint8_t h01_384[] = { 0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D,
0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85,
0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61,
0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A,
0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47,
0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04 };
static const uint8_t h01_512[] = { 0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5,
0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E,
0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59,
0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6,
0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C,
0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58,
0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3,
0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26 };
/**
* @brief expected SHA3-256 hash for test 02
msg = '4A4F202484512526'
md_256 = BA4FB009D57A5CEB85FC64D54E5C55A55854B41CC47AD15294BC41F32165DFBA
md_384 = 89DBF4C39B8FB46FDF0A6926CEC0355A4BDBF9C6A446E140B7C8BD08FF6F489F
205DAF8EFFE160F437F67491EF897C23
md_512 = 150D787D6EB49670C2A4CCD17E6CCE7A04C1FE30FCE03D1EF2501752D92AE04C
B345FD42E51038C83B2B4F8FD438D1B4B55CC588C6B913132F1A658FB122CB52
*/
static const uint8_t m02[] = { 0x4A, 0x4F, 0x20, 0x24, 0x84, 0x51, 0x25, 0x26 };
size_t m02_len = sizeof(m02);
static const uint8_t m02_1[] = { 0x4A, 0x4F };
size_t m02_1_len = sizeof(m02_1);
static const uint8_t m02_2[] = { 0x20, 0x24, 0x84, 0x51, 0x25, 0x26 };
size_t m02_2_len = sizeof(m02_2);
static const uint8_t h02_256[] = { 0xBA, 0x4F, 0xB0, 0x09, 0xD5, 0x7A, 0x5C, 0xEB,
0x85, 0xFC, 0x64, 0xD5, 0x4E, 0x5C, 0x55, 0xA5,
0x58, 0x54, 0xB4, 0x1C, 0xC4, 0x7A, 0xD1, 0x52,
0x94, 0xBC, 0x41, 0xF3, 0x21, 0x65, 0xDF, 0xBA };
static const uint8_t h02_384[] = { 0x89, 0xDB, 0xF4, 0xC3, 0x9B, 0x8F, 0xB4, 0x6F,
0xDF, 0x0A, 0x69, 0x26, 0xCE, 0xC0, 0x35, 0x5A,
0x4B, 0xDB, 0xF9, 0xC6, 0xA4, 0x46, 0xE1, 0x40,
0xB7, 0xC8, 0xBD, 0x08, 0xFF, 0x6F, 0x48, 0x9F,
0x20, 0x5D, 0xAF, 0x8E, 0xFF, 0xE1, 0x60, 0xF4,
0x37, 0xF6, 0x74, 0x91, 0xEF, 0x89, 0x7C, 0x23 };
static const uint8_t h02_512[] = { 0x15, 0x0D, 0x78, 0x7D, 0x6E, 0xB4, 0x96, 0x70,
0xC2, 0xA4, 0xCC, 0xD1, 0x7E, 0x6C, 0xCE, 0x7A,
0x04, 0xC1, 0xFE, 0x30, 0xFC, 0xE0, 0x3D, 0x1E,
0xF2, 0x50, 0x17, 0x52, 0xD9, 0x2A, 0xE0, 0x4C,
0xB3, 0x45, 0xFD, 0x42, 0xE5, 0x10, 0x38, 0xC8,
0x3B, 0x2B, 0x4F, 0x8F, 0xD4, 0x38, 0xD1, 0xB4,
0xB5, 0x5C, 0xC5, 0x88, 0xC6, 0xB9, 0x13, 0x13,
0x2F, 0x1A, 0x65, 0x8F, 0xB1, 0x22, 0xCB, 0x52 };
/* @brief expected SHA3-256 hash for test 03
msg = '2B6DB7CED8665EBE9DEB080295218426BDAA7C6DA9ADD2088932CDFFBAA1C14129
BCCDD70F369EFB149285858D2B1D155D14DE2FDB680A8B027284055182A0CAE275
234CC9C92863C1B4AB66F304CF0621CD54565F5BFF461D3B461BD40DF28198E373
2501B4860EADD503D26D6E69338F4E0456E9E9BAF3D827AE685FB1D817'
md_256 = B7D031AA69B7B4D26A35B896D761314F1D61EB12DCC1E72AAF61B9CD48003AF9
md_384 = 8FD01909381EB713803419361D8E82E92476A08EDCC225BB8A135D215CB48D07
B074624FCF2E73E666DBA59334719839
md_512 = 4FAB45806B4628068458B5D0A2D4BF101B8BFC9276EF86AD5D883765C43F72CE
8A5F7B4C5B535A915130BB185E699AB62228014E54DF790C0E93AADBE7E39E19
*/
static const uint8_t m03[] = { 0x2B, 0x6D, 0xB7, 0xCE, 0xD8, 0x66, 0x5E, 0xBE, 0x9D,
0xEB, 0x08, 0x02, 0x95, 0x21, 0x84, 0x26, 0xBD, 0xAA,
0x7C, 0x6D, 0xA9, 0xAD, 0xD2, 0x08, 0x89, 0x32, 0xCD,
0xFF, 0xBA, 0xA1, 0xC1, 0x41, 0x29, 0xBC, 0xCD, 0xD7,
0x0F, 0x36, 0x9E, 0xFB, 0x14, 0x92, 0x85, 0x85, 0x8D,
0x2B, 0x1D, 0x15, 0x5D, 0x14, 0xDE, 0x2F, 0xDB, 0x68,
0x0A, 0x8B, 0x02, 0x72, 0x84, 0x05, 0x51, 0x82, 0xA0,
0xCA, 0xE2, 0x75, 0x23, 0x4C, 0xC9, 0xC9, 0x28, 0x63,
0xC1, 0xB4, 0xAB, 0x66, 0xF3, 0x04, 0xCF, 0x06, 0x21,
0xCD, 0x54, 0x56, 0x5F, 0x5B, 0xFF, 0x46, 0x1D, 0x3B,
0x46, 0x1B, 0xD4, 0x0D, 0xF2, 0x81, 0x98, 0xE3, 0x73,
0x25, 0x01, 0xB4, 0x86, 0x0E, 0xAD, 0xD5, 0x03, 0xD2,
0x6D, 0x6E, 0x69, 0x33, 0x8F, 0x4E, 0x04, 0x56, 0xE9,
0xE9, 0xBA, 0xF3, 0xD8, 0x27, 0xAE, 0x68, 0x5F, 0xB1,
0xD8, 0x17 };
const size_t m03_len = sizeof(m03);
static const uint8_t m03_1[] = { 0x2B, 0x6D, 0xB7, 0xCE, 0xD8, 0x66, 0x5E, 0xBE, 0x9D,
0xEB, 0x08, 0x02, 0x95, 0x21, 0x84, 0x26, 0xBD };
size_t m03_1_len = sizeof(m03_1);
static const uint8_t m03_2[] = { 0xAA, 0x7C, 0x6D, 0xA9, 0xAD, 0xD2, 0x08, 0x89, 0x32,
0xCD, 0xFF, 0xBA, 0xA1, 0xC1, 0x41, 0x29, 0xBC, 0xCD,
0xD7, 0x0F, 0x36, 0x9E, 0xFB, 0x14, 0x92, 0x85, 0x85,
0x8D, 0x2B, 0x1D, 0x15, 0x5D, 0x14, 0xDE, 0x2F, 0xDB,
0x68, 0x0A, 0x8B, 0x02, 0x72, 0x84, 0x05, 0x51, 0x82,
0xA0, 0xCA, 0xE2, 0x75, 0x23, 0x4C, 0xC9, 0xC9, 0x28,
0x63, 0xC1, 0xB4, 0xAB, 0x66, 0xF3, 0x04, 0xCF, 0x06,
0x21, 0xCD, 0x54, 0x56, 0x5F, 0x5B, 0xFF, 0x46, 0x1D,
0x3B, 0x46, 0x1B, 0xD4, 0x0D, 0xF2, 0x81, 0x98, 0xE3,
0x73, 0x25, 0x01, 0xB4, 0x86, 0x0E, 0xAD, 0xD5, 0x03,
0xD2, 0x6D, 0x6E, 0x69, 0x33, 0x8F, 0x4E, 0x04, 0x56,
0xE9, 0xE9, 0xBA, 0xF3, 0xD8, 0x27, 0xAE, 0x68, 0x5F,
0xB1, 0xD8, 0x17 };
size_t m03_2_len = sizeof(m03_2);
static const uint8_t h03_256[] = { 0xB7, 0xD0, 0x31, 0xAA, 0x69, 0xB7, 0xB4, 0xD2,
0x6A, 0x35, 0xB8, 0x96, 0xD7, 0x61, 0x31, 0x4F,
0x1D, 0x61, 0xEB, 0x12, 0xDC, 0xC1, 0xE7, 0x2A,
0xAF, 0x61, 0xB9, 0xCD, 0x48, 0x00, 0x3A, 0xF9 };
static const uint8_t h03_384[] = { 0x8F, 0xD0, 0x19, 0x09, 0x38, 0x1E, 0xB7, 0x13,
0x80, 0x34, 0x19, 0x36, 0x1D, 0x8E, 0x82, 0xE9,
0x24, 0x76, 0xA0, 0x8E, 0xDC, 0xC2, 0x25, 0xBB,
0x8A, 0x13, 0x5D, 0x21, 0x5C, 0xB4, 0x8D, 0x07,
0xB0, 0x74, 0x62, 0x4F, 0xCF, 0x2E, 0x73, 0xE6,
0x66, 0xDB, 0xA5, 0x93, 0x34, 0x71, 0x98, 0x39 };
static const uint8_t h03_512[] = { 0x4F, 0xAB, 0x45, 0x80, 0x6B, 0x46, 0x28, 0x06,
0x84, 0x58, 0xB5, 0xD0, 0xA2, 0xD4, 0xBF, 0x10,
0x1B, 0x8B, 0xFC, 0x92, 0x76, 0xEF, 0x86, 0xAD,
0x5D, 0x88, 0x37, 0x65, 0xC4, 0x3F, 0x72, 0xCE,
0x8A, 0x5F, 0x7B, 0x4C, 0x5B, 0x53, 0x5A, 0x91,
0x51, 0x30, 0xBB, 0x18, 0x5E, 0x69, 0x9A, 0xB6,
0x22, 0x28, 0x01, 0x4E, 0x54, 0xDF, 0x79, 0x0C,
0x0E, 0x93, 0xAA, 0xDB, 0xE7, 0xE3, 0x9E, 0x19 };
/* @brief expected SHA3-256 hash for test 04
msg = '3A3A819C48EFDE2AD914FBF00E18AB6BC4F14513AB27D0C178A188B61431E7F562
3CB66B23346775D386B50E982C493ADBBFC54B9A3CD383382336A1A0B2150A1535
8F336D03AE18F666C7573D55C4FD181C29E6CCFDE63EA35F0ADF5885CFC0A3D84A
2B2E4DD24496DB789E663170CEF74798AA1BBCD4574EA0BBA40489D764B2F83AAD
C66B148B4A0CD95246C127D5871C4F11418690A5DDF01246A0C80A43C70088B618
3639DCFDA4125BD113A8F49EE23ED306FAAC576C3FB0C1E256671D817FC2534A52
F5B439F72E424DE376F4C565CCA82307DD9EF76DA5B7C4EB7E085172E328807C02
D011FFBF33785378D79DC266F6A5BE6BB0E4A92ECEEBAEB1'
md_256 = C11F3522A8FB7B3532D80B6D40023A92B489ADDAD93BF5D64B23F35E9663521C
md_384 = 128DC611762BE9B135B3739484CFAADCA7481D68514F3DFD6F5D78BB1863AE68
130835CDC7061A7ED964B32F1DB75EE1
md_512 = 6E8B8BD195BDD560689AF2348BDC74AB7CD05ED8B9A57711E9BE71E9726FDA45
91FEE12205EDACAF82FFBBAF16DFF9E702A708862080166C2FF6BA379BC7FFC2
*/
static const uint8_t m04[] = { 0x3A, 0x3A, 0x81, 0x9C, 0x48, 0xEF, 0xDE, 0x2A,
0xD9, 0x14, 0xFB, 0xF0, 0x0E, 0x18, 0xAB, 0x6B,
0xC4, 0xF1, 0x45, 0x13, 0xAB, 0x27, 0xD0, 0xC1,
0x78, 0xA1, 0x88, 0xB6, 0x14, 0x31, 0xE7, 0xF5,
0x62, 0x3C, 0xB6, 0x6B, 0x23, 0x34, 0x67, 0x75,
0xD3, 0x86, 0xB5, 0x0E, 0x98, 0x2C, 0x49, 0x3A,
0xDB, 0xBF, 0xC5, 0x4B, 0x9A, 0x3C, 0xD3, 0x83,
0x38, 0x23, 0x36, 0xA1, 0xA0, 0xB2, 0x15, 0x0A,
0x15, 0x35, 0x8F, 0x33, 0x6D, 0x03, 0xAE, 0x18,
0xF6, 0x66, 0xC7, 0x57, 0x3D, 0x55, 0xC4, 0xFD,
0x18, 0x1C, 0x29, 0xE6, 0xCC, 0xFD, 0xE6, 0x3E,
0xA3, 0x5F, 0x0A, 0xDF, 0x58, 0x85, 0xCF, 0xC0,
0xA3, 0xD8, 0x4A, 0x2B, 0x2E, 0x4D, 0xD2, 0x44,
0x96, 0xDB, 0x78, 0x9E, 0x66, 0x31, 0x70, 0xCE,
0xF7, 0x47, 0x98, 0xAA, 0x1B, 0xBC, 0xD4, 0x57,
0x4E, 0xA0, 0xBB, 0xA4, 0x04, 0x89, 0xD7, 0x64,
0xB2, 0xF8, 0x3A, 0xAD, 0xC6, 0x6B, 0x14, 0x8B,
0x4A, 0x0C, 0xD9, 0x52, 0x46, 0xC1, 0x27, 0xD5,
0x87, 0x1C, 0x4F, 0x11, 0x41, 0x86, 0x90, 0xA5,
0xDD, 0xF0, 0x12, 0x46, 0xA0, 0xC8, 0x0A, 0x43,
0xC7, 0x00, 0x88, 0xB6, 0x18, 0x36, 0x39, 0xDC,
0xFD, 0xA4, 0x12, 0x5B, 0xD1, 0x13, 0xA8, 0xF4,
0x9E, 0xE2, 0x3E, 0xD3, 0x06, 0xFA, 0xAC, 0x57,
0x6C, 0x3F, 0xB0, 0xC1, 0xE2, 0x56, 0x67, 0x1D,
0x81, 0x7F, 0xC2, 0x53, 0x4A, 0x52, 0xF5, 0xB4,
0x39, 0xF7, 0x2E, 0x42, 0x4D, 0xE3, 0x76, 0xF4,
0xC5, 0x65, 0xCC, 0xA8, 0x23, 0x07, 0xDD, 0x9E,
0xF7, 0x6D, 0xA5, 0xB7, 0xC4, 0xEB, 0x7E, 0x08,
0x51, 0x72, 0xE3, 0x28, 0x80, 0x7C, 0x02, 0xD0,
0x11, 0xFF, 0xBF, 0x33, 0x78, 0x53, 0x78, 0xD7,
0x9D, 0xC2, 0x66, 0xF6, 0xA5, 0xBE, 0x6B, 0xB0,
0xE4, 0xA9, 0x2E, 0xCE, 0xEB, 0xAE, 0xB1 };
size_t m04_len = sizeof(m04);
static const uint8_t m04_1[] = { 0x3A, 0x3A, 0x81, 0x9C, 0x48, 0xEF, 0xDE, 0x2A,
0xD9, 0x14, 0xFB, 0xF0, 0x0E, 0x18, 0xAB, 0x6B,
0xC4, 0xF1, 0x45, 0x13, 0xAB, 0x27, 0xD0, 0xC1,
0x78, 0xA1, 0x88, 0xB6, 0x14, 0x31, 0xE7, 0xF5,
0x62, 0x3C, 0xB6, 0x6B, 0x23, 0x34, 0x67, 0x75,
0xD3, 0x86, 0xB5, 0x0E, 0x98, 0x2C, 0x49, 0x3A,
0xDB, 0xBF, 0xC5, 0x4B, 0x9A, 0x3C, 0xD3, 0x83,
0x38, 0x23, 0x36, 0xA1, 0xA0, 0xB2, 0x15, 0x0A,
0x15, 0x35, 0x8F, 0x33, 0x6D, 0x03, 0xAE, 0x18,
0xF6, 0x66, 0xC7, 0x57, 0x3D, 0x55, 0xC4, 0xFD,
0x18, 0x1C, 0x29, 0xE6, 0xCC, 0xFD, 0xE6, 0x3E,
0xA3, 0x5F, 0x0A, 0xDF, 0x58, 0x85, 0xCF, 0xC0,
0xA3, 0xD8, 0x4A, 0x2B, 0x2E, 0x4D, 0xD2, 0x44,
0x96, 0xDB, 0x78, 0x9E, 0x66, 0x31, 0x70, 0xCE,
0xF7, 0x47, 0x98, 0xAA, 0x1B, 0xBC, 0xD4, 0x57,
0x4E, 0xA0, 0xBB, 0xA4, 0x04, 0x89, 0xD7, 0x64,
0xB2, 0xF8, 0x3A, 0xAD, 0xC6, 0x6B, 0x14, 0x8B,
0x4A, 0x0C, 0xD9, 0x52, 0x46, 0xC1, 0x27, 0xD5,
0x87, 0x1C, 0x4F, 0x11, 0x41, 0x86, 0x90, 0xA5,
0xDD, 0xF0, 0x12, 0x46, 0xA0, 0xC8, 0x0A, 0x43,
0xC7, 0x00, 0x88, 0xB6, 0x18, 0x36, 0x39, 0xDC,
0xFD, 0xA4, 0x12, 0x5B, 0xD1, 0x13, 0xA8, 0xF4,
0x9E, 0xE2, 0x3E, 0xD3, 0x06, 0xFA, 0xAC, 0x57,
0x6C, 0x3F, 0xB0, 0xC1, 0xE2, 0x56, 0x67, 0x1D,
0x81, 0x7F, 0xC2, 0x53, 0x4A, 0x52, 0xF5, 0xB4,
0x39, 0xF7, 0x2E, 0x42, 0x4D, 0xE3, 0x76, 0xF4,
0xC5, 0x65, 0xCC, 0xA8, 0x23, 0x07, 0xDD, 0x9E,
0xF7, 0x6D, 0xA5, 0xB7, 0xC4, 0xEB, 0x7E, 0x08,
0x51, 0x72, 0xE3, 0x28, 0x80, 0x7C, 0x02, 0xD0,
0x11, 0xFF, 0xBF, 0x33, 0x78, 0x53, 0x78, 0xD7,
0x9D, 0xC2, 0x66, 0xF6, 0xA5, 0xBE, 0x6B, 0xB0 };
size_t m04_1_len = sizeof(m04_1);
static const uint8_t m04_2[] = { 0xE4, 0xA9, 0x2E, 0xCE, 0xEB, 0xAE, 0xB1 };
size_t m04_2_len = sizeof(m04_2);
static const uint8_t h04_256[] = { 0xC1, 0x1F, 0x35, 0x22, 0xA8, 0xFB, 0x7B, 0x35,
0x32, 0xD8, 0x0B, 0x6D, 0x40, 0x02, 0x3A, 0x92,
0xB4, 0x89, 0xAD, 0xDA, 0xD9, 0x3B, 0xF5, 0xD6,
0x4B, 0x23, 0xF3, 0x5E, 0x96, 0x63, 0x52, 0x1C };
static const uint8_t h04_384[] = { 0x12, 0x8D, 0xC6, 0x11, 0x76, 0x2B, 0xE9, 0xB1,
0x35, 0xB3, 0x73, 0x94, 0x84, 0xCF, 0xAA, 0xDC,
0xA7, 0x48, 0x1D, 0x68, 0x51, 0x4F, 0x3D, 0xFD,
0x6F, 0x5D, 0x78, 0xBB, 0x18, 0x63, 0xAE, 0x68,
0x13, 0x08, 0x35, 0xCD, 0xC7, 0x06, 0x1A, 0x7E,
0xD9, 0x64, 0xB3, 0x2F, 0x1D, 0xB7, 0x5E, 0xE1 };
static const uint8_t h04_512[] = { 0x6E, 0x8B, 0x8B, 0xD1, 0x95, 0xBD, 0xD5, 0x60,
0x68, 0x9A, 0xF2, 0x34, 0x8B, 0xDC, 0x74, 0xAB,
0x7C, 0xD0, 0x5E, 0xD8, 0xB9, 0xA5, 0x77, 0x11,
0xE9, 0xBE, 0x71, 0xE9, 0x72, 0x6F, 0xDA, 0x45,
0x91, 0xFE, 0xE1, 0x22, 0x05, 0xED, 0xAC, 0xAF,
0x82, 0xFF, 0xBB, 0xAF, 0x16, 0xDF, 0xF9, 0xE7,
0x02, 0xA7, 0x08, 0x86, 0x20, 0x80, 0x16, 0x6C,
0x2F, 0xF6, 0xBA, 0x37, 0x9B, 0xC7, 0xFF, 0xC2 };
static const uint8_t mfail[] = { 0x4A, 0x4F, 0x20, 0x24, 0x84, 0x51, 0x25, 0x27 };
size_t mfail_len = sizeof(mfail);
static const uint8_t hfail_256[] = { 0xBA, 0x4F, 0xB0, 0x09, 0xD5, 0x7A, 0x5C, 0xEB,
0x85, 0xFC, 0x64, 0xD5, 0x4E, 0x5C, 0x55, 0xA5,
0x58, 0x54, 0xB4, 0x1C, 0xC4, 0x7A, 0xD1, 0x52,
0x94, 0xBC, 0x41, 0xF3, 0x21, 0x65, 0xDF, 0xBA };
static const uint8_t hfail_384[] = { 0x89, 0xDB, 0xF4, 0xC3, 0x9B, 0x8F, 0xB4, 0x6F,
0xDF, 0x0A, 0x69, 0x26, 0xCE, 0xC0, 0x35, 0x5A,
0x4B, 0xDB, 0xF9, 0xC6, 0xA4, 0x46, 0xE1, 0x40,
0xB7, 0xC8, 0xBD, 0x08, 0xFF, 0x6F, 0x48, 0x9F,
0x20, 0x5D, 0xAF, 0x8E, 0xFF, 0xE1, 0x60, 0xF4,
0x37, 0xF6, 0x74, 0x91, 0xEF, 0x89, 0x7C, 0x23 };
static const uint8_t hfail_512[] = { 0x15, 0x0D, 0x78, 0x7D, 0x6E, 0xB4, 0x96, 0x70,
0xC2, 0xA4, 0xCC, 0xD1, 0x7E, 0x6C, 0xCE, 0x7A,
0x04, 0xC1, 0xFE, 0x30, 0xFC, 0xE0, 0x3D, 0x1E,
0xF2, 0x50, 0x17, 0x52, 0xD9, 0x2A, 0xE0, 0x4C,
0xB3, 0x45, 0xFD, 0x42, 0xE5, 0x10, 0x38, 0xC8,
0x3B, 0x2B, 0x4F, 0x8F, 0xD4, 0x38, 0xD1, 0xB4,
0xB5, 0x5C, 0xC5, 0x88, 0xC6, 0xB9, 0x13, 0x13,
0x2F, 0x1A, 0x65, 0x8F, 0xB1, 0x22, 0xCB, 0x52 };
static int calc_and_compare_hash_256(const uint8_t *msg, size_t msg_len, const uint8_t *expected)
{
static unsigned char hash[SHA3_256_DIGEST_LENGTH];
sha3_256(hash, msg, msg_len);
return (memcmp(expected, hash, sizeof(hash)) == 0);
}
static int calc_steps_and_compare_hash_256(const uint8_t *msg1, size_t msg1_len,
const uint8_t *msg2, size_t msg2_len, const uint8_t *expected)
{
static unsigned char hash[SHA3_256_DIGEST_LENGTH];
keccak_state_t state;
sha3_256_init(&state);
sha3_update(&state, msg1, msg1_len);
sha3_update(&state, msg2, msg2_len);
sha3_256_final(&state, hash);
return (memcmp(expected, hash, sizeof(hash)) == 0);
}
static int calc_and_compare_hash_384(const uint8_t *msg, size_t msg_len, const uint8_t *expected)
{
static unsigned char hash[SHA3_384_DIGEST_LENGTH];
sha3_384(hash, msg, msg_len);
return (memcmp(expected, hash, sizeof(hash)) == 0);
}
static int calc_steps_and_compare_hash_384(const uint8_t *msg1, size_t msg1_len,
const uint8_t *msg2, size_t msg2_len, const uint8_t *expected)
{
static unsigned char hash[SHA3_384_DIGEST_LENGTH];
keccak_state_t state;
sha3_384_init(&state);
sha3_update(&state, msg1, msg1_len);
sha3_update(&state, msg2, msg2_len);
sha3_384_final(&state, hash);
return (memcmp(expected, hash, sizeof(hash)) == 0);
}
static int calc_and_compare_hash_512(const uint8_t *msg, size_t msg_len, const uint8_t *expected)
{
static unsigned char hash[SHA3_512_DIGEST_LENGTH];
sha3_512(hash, msg, msg_len);
return (memcmp(expected, hash, sizeof(hash)) == 0);
}
static int calc_steps_and_compare_hash_512(const uint8_t *msg1, size_t msg1_len,
const uint8_t *msg2, size_t msg2_len, const uint8_t *expected)
{
static unsigned char hash[SHA3_512_DIGEST_LENGTH];
keccak_state_t state;
sha3_512_init(&state);
sha3_update(&state, msg1, msg1_len);
sha3_update(&state, msg2, msg2_len);
sha3_512_final(&state, hash);
return (memcmp(expected, hash, sizeof(hash)) == 0);
}
static void test_hashes_sha3_hash_sequence_01(void)
{
TEST_ASSERT(calc_and_compare_hash_256(m01, m01_len, h01_256));
TEST_ASSERT(calc_steps_and_compare_hash_256(m01_1, m01_1_len, m01_2, m01_2_len, h01_256));
TEST_ASSERT(calc_and_compare_hash_384(m01, m01_len, h01_384));
TEST_ASSERT(calc_steps_and_compare_hash_384(m01_1, m01_1_len, m01_2, m01_2_len, h01_384));
TEST_ASSERT(calc_and_compare_hash_512(m01, m01_len, h01_512));
TEST_ASSERT(calc_steps_and_compare_hash_512(m01_1, m01_1_len, m01_2, m01_2_len, h01_512));
}
static void test_hashes_sha3_hash_sequence_02(void)
{
TEST_ASSERT(calc_and_compare_hash_256(m02, m02_len, h02_256));
TEST_ASSERT(calc_steps_and_compare_hash_256(m02_1, m02_1_len, m02_2, m02_2_len, h02_256));
TEST_ASSERT(calc_and_compare_hash_384(m02, m02_len, h02_384));
TEST_ASSERT(calc_steps_and_compare_hash_384(m02_1, m02_1_len, m02_2, m02_2_len, h02_384));
TEST_ASSERT(calc_and_compare_hash_512(m02, m02_len, h02_512));
TEST_ASSERT(calc_steps_and_compare_hash_512(m02_1, m02_1_len, m02_2, m02_2_len, h02_512));
}
static void test_hashes_sha3_hash_sequence_03(void)
{
TEST_ASSERT(calc_and_compare_hash_256(m03, m03_len, h03_256));
TEST_ASSERT(calc_steps_and_compare_hash_256(m03_1, m03_1_len, m03_2, m03_2_len, h03_256));
TEST_ASSERT(calc_and_compare_hash_384(m03, m03_len, h03_384));
TEST_ASSERT(calc_steps_and_compare_hash_384(m03_1, m03_1_len, m03_2, m03_2_len, h03_384));
TEST_ASSERT(calc_and_compare_hash_512(m03, m03_len, h03_512));
TEST_ASSERT(calc_steps_and_compare_hash_512(m03_1, m03_1_len, m03_2, m03_2_len, h03_512));
}
static void test_hashes_sha3_hash_sequence_04(void)
{
TEST_ASSERT(calc_and_compare_hash_256(m04, m04_len, h04_256));
TEST_ASSERT(calc_steps_and_compare_hash_256(m04_1, m04_1_len, m04_2, m04_2_len, h04_256));
TEST_ASSERT(calc_and_compare_hash_384(m04, m04_len, h04_384));
TEST_ASSERT(calc_steps_and_compare_hash_384(m04_1, m04_1_len, m04_2, m04_2_len, h04_384));
TEST_ASSERT(calc_and_compare_hash_512(m04, m04_len, h04_512));
TEST_ASSERT(calc_steps_and_compare_hash_512(m04_1, m04_1_len, m04_2, m04_2_len, h04_512));
}
static void test_hashes_sha3_hash_sequence_failing_compare(void)
{
/* failing compare (message from testcase 02 alterered slightly) */
TEST_ASSERT(!calc_and_compare_hash_256(mfail, mfail_len, hfail_256));
TEST_ASSERT(!calc_and_compare_hash_384(mfail, mfail_len, hfail_384));
TEST_ASSERT(!calc_and_compare_hash_512(mfail, mfail_len, hfail_512));
}
Test *tests_hashes_sha3_tests(void)
{
EMB_UNIT_TESTFIXTURES(fixtures) {
new_TestFixture(test_hashes_sha3_hash_sequence_01),
new_TestFixture(test_hashes_sha3_hash_sequence_02),
new_TestFixture(test_hashes_sha3_hash_sequence_03),
new_TestFixture(test_hashes_sha3_hash_sequence_04),
new_TestFixture(test_hashes_sha3_hash_sequence_failing_compare),
};
EMB_UNIT_TESTCALLER(hashes_sha3_tests, NULL, NULL,
fixtures);
return (Test *)&hashes_sha3_tests;
}
......@@ -28,4 +28,5 @@ void tests_hashes(void)
TESTS_RUN(tests_hashes_sha256_tests());
TESTS_RUN(tests_hashes_sha256_hmac_tests());
TESTS_RUN(tests_hashes_sha256_chain_tests());
TESTS_RUN(tests_hashes_sha3_tests());
}
......@@ -72,6 +72,13 @@ Test *tests_hashes_sha256_hmac_tests(void);
*/
Test *tests_hashes_sha256_chain_tests(void);
/**
* @brief Generates tests for hashes/sha3.h
*
* @return embUnit tests if successful, NULL if not.
*/
Test *tests_hashes_sha3_tests(void);
#ifdef __cplusplus
}
#endif
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment