Skip to content

Commit dddf507

Browse files
committed
Add SHA3 hashing
- added these variants: SHA3-256, SHA3-384, SHA3-512 - reordered also the hashing id's - added some notes about them in DOC/Hashes.txt Signed-off-by: Tino Reichardt <[email protected]>
1 parent 9b8a493 commit dddf507

25 files changed

+496
-35
lines changed

C/hashes/README.md

Lines changed: 0 additions & 4 deletions
This file was deleted.

C/hashes/md2.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

22
/*
3+
* Taken from lib/crypto/* of samba-4.5.8.tar.gz.
4+
*
35
* Copyright (c) 2006 Kungliga Tekniska Högskolan
46
* (Royal Institute of Technology, Stockholm, Sweden).
57
* All rights reserved.

C/hashes/md2.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

22
/*
3+
* Taken from lib/crypto/* of samba-4.5.8.tar.gz.
4+
*
35
* Copyright (c) 2006 Kungliga Tekniska Högskolan
46
* (Royal Institute of Technology, Stockholm, Sweden).
57
* All rights reserved.

C/hashes/md4.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

22
/*
3+
* Taken from lib/crypto/* of samba-4.5.8.tar.gz.
4+
*
35
* Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
46
* (Royal Institute of Technology, Stockholm, Sweden).
57
* All rights reserved.

C/hashes/md4.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

22
/*
3+
* Taken from lib/crypto/* of samba-4.5.8.tar.gz.
4+
*
35
* Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
46
* (Royal Institute of Technology, Stockholm, Sweden).
57
* All rights reserved.

C/hashes/md5.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

22
/*
3+
* Taken from lib/crypto/* of samba-4.5.8.tar.gz.
4+
*
35
* Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
46
* (Royal Institute of Technology, Stockholm, Sweden).
57
* All rights reserved.

C/hashes/md5.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

22
/*
3+
* Taken from lib/crypto/* of samba-4.5.8.tar.gz.
4+
*
35
* Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan
46
* (Royal Institute of Technology, Stockholm, Sweden).
57
* All rights reserved.

C/hashes/sha3.c

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
2+
/**
3+
* Canonical implementation of Init/Update/Finalize for SHA-3 byte input.
4+
* Based on code from https://github.com/brainhub/SHA3IUF/
5+
*
6+
* This work is released into the public domain with CC0 1.0.
7+
*
8+
* Copyright (c) 2015. Andrey Jivsov <[email protected]>
9+
* Copyright (c) 2023 Tino Reichardt <[email protected]>
10+
*/
11+
12+
#include <stdio.h>
13+
#include <stdint.h>
14+
#include <string.h>
15+
16+
#include "sha3.h"
17+
18+
#define SHA3_ASSERT( x )
19+
20+
#if defined(_MSC_VER)
21+
#define SHA3_CONST(x) x
22+
#else
23+
#define SHA3_CONST(x) x##L
24+
#endif
25+
26+
/*
27+
* This flag is used to configure "pure" Keccak, as opposed to NIST SHA3.
28+
*/
29+
#define SHA3_USE_KECCAK_FLAG 0x80000000
30+
#define SHA3_CW(x) ((x) & (~SHA3_USE_KECCAK_FLAG))
31+
32+
#ifndef SHA3_ROTL64
33+
#define SHA3_ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
34+
#endif
35+
36+
static const uint64_t keccakf_rndc[24] = {
37+
SHA3_CONST(0x0000000000000001UL), SHA3_CONST(0x0000000000008082UL),
38+
SHA3_CONST(0x800000000000808aUL), SHA3_CONST(0x8000000080008000UL),
39+
SHA3_CONST(0x000000000000808bUL), SHA3_CONST(0x0000000080000001UL),
40+
SHA3_CONST(0x8000000080008081UL), SHA3_CONST(0x8000000000008009UL),
41+
SHA3_CONST(0x000000000000008aUL), SHA3_CONST(0x0000000000000088UL),
42+
SHA3_CONST(0x0000000080008009UL), SHA3_CONST(0x000000008000000aUL),
43+
SHA3_CONST(0x000000008000808bUL), SHA3_CONST(0x800000000000008bUL),
44+
SHA3_CONST(0x8000000000008089UL), SHA3_CONST(0x8000000000008003UL),
45+
SHA3_CONST(0x8000000000008002UL), SHA3_CONST(0x8000000000000080UL),
46+
SHA3_CONST(0x000000000000800aUL), SHA3_CONST(0x800000008000000aUL),
47+
SHA3_CONST(0x8000000080008081UL), SHA3_CONST(0x8000000000008080UL),
48+
SHA3_CONST(0x0000000080000001UL), SHA3_CONST(0x8000000080008008UL)
49+
};
50+
51+
static const unsigned keccakf_rotc[24] = {
52+
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62,
53+
18, 39, 61, 20, 44
54+
};
55+
56+
static const unsigned keccakf_piln[24] = {
57+
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20,
58+
14, 22, 9, 6, 1
59+
};
60+
61+
/* generally called after SHA3_KECCAK_SPONGE_WORDS-ctx->capacityWords words
62+
* are XORed into the state s
63+
*/
64+
static void keccakf(uint64_t s[25])
65+
{
66+
int i, j, round;
67+
uint64_t t, bc[5];
68+
#define KECCAK_ROUNDS 24
69+
70+
for (round = 0; round < KECCAK_ROUNDS; round++) {
71+
72+
/* Theta */
73+
for (i = 0; i < 5; i++)
74+
bc[i] =
75+
s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
76+
77+
for (i = 0; i < 5; i++) {
78+
t = bc[(i + 4) % 5] ^ SHA3_ROTL64(bc[(i + 1) % 5], 1);
79+
for (j = 0; j < 25; j += 5)
80+
s[j + i] ^= t;
81+
}
82+
83+
/* Rho Pi */
84+
t = s[1];
85+
for (i = 0; i < 24; i++) {
86+
j = keccakf_piln[i];
87+
bc[0] = s[j];
88+
s[j] = SHA3_ROTL64(t, keccakf_rotc[i]);
89+
t = bc[0];
90+
}
91+
92+
/* Chi */
93+
for (j = 0; j < 25; j += 5) {
94+
for (i = 0; i < 5; i++)
95+
bc[i] = s[j + i];
96+
for (i = 0; i < 5; i++)
97+
s[j + i] ^=
98+
(~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
99+
}
100+
101+
/* Iota */
102+
s[0] ^= keccakf_rndc[round];
103+
}
104+
}
105+
106+
/* *************************** Public Inteface ************************ */
107+
108+
void SHA3_Init(SHA3_CTX * ctx, unsigned bitSize)
109+
{
110+
memset(ctx, 0, sizeof(*ctx));
111+
ctx->digest_length = bitSize;
112+
ctx->capacityWords = 2 * bitSize / (8 * sizeof(uint64_t));
113+
}
114+
115+
void SHA3_Update(SHA3_CTX * ctx, void const *bufIn, size_t len)
116+
{
117+
/* 0...7 -- how much is needed to have a word */
118+
unsigned old_tail = (8 - ctx->byteIndex) & 7;
119+
120+
size_t words;
121+
size_t tail;
122+
size_t i;
123+
124+
const uint8_t *buf = bufIn;
125+
126+
SHA3_ASSERT(ctx->byteIndex < 8);
127+
SHA3_ASSERT(ctx->wordIndex < sizeof(ctx->u.s) / sizeof(ctx->u.s[0]));
128+
129+
if (len < old_tail) { /* have no complete word or haven't started
130+
* the word yet */
131+
/* endian-independent code follows: */
132+
while (len--)
133+
ctx->saved |=
134+
(uint64_t) (*(buf++)) << ((ctx->byteIndex++) * 8);
135+
SHA3_ASSERT(ctx->byteIndex < 8);
136+
return;
137+
}
138+
139+
if (old_tail) { /* will have one word to process */
140+
/* endian-independent code follows: */
141+
len -= old_tail;
142+
while (old_tail--)
143+
ctx->saved |=
144+
(uint64_t) (*(buf++)) << ((ctx->byteIndex++) * 8);
145+
146+
/* now ready to add saved to the sponge */
147+
ctx->u.s[ctx->wordIndex] ^= ctx->saved;
148+
SHA3_ASSERT(ctx->byteIndex == 8);
149+
ctx->byteIndex = 0;
150+
ctx->saved = 0;
151+
if (++ctx->wordIndex ==
152+
(SHA3_KECCAK_SPONGE_WORDS - SHA3_CW(ctx->capacityWords))) {
153+
keccakf(ctx->u.s);
154+
ctx->wordIndex = 0;
155+
}
156+
}
157+
158+
/* now work in full words directly from input */
159+
160+
SHA3_ASSERT(ctx->byteIndex == 0);
161+
162+
words = len / sizeof(uint64_t);
163+
tail = len - words * sizeof(uint64_t);
164+
165+
for (i = 0; i < words; i++, buf += sizeof(uint64_t)) {
166+
const uint64_t t = (uint64_t) (buf[0]) |
167+
((uint64_t) (buf[1]) << 8 * 1) |
168+
((uint64_t) (buf[2]) << 8 * 2) |
169+
((uint64_t) (buf[3]) << 8 * 3) |
170+
((uint64_t) (buf[4]) << 8 * 4) |
171+
((uint64_t) (buf[5]) << 8 * 5) |
172+
((uint64_t) (buf[6]) << 8 * 6) |
173+
((uint64_t) (buf[7]) << 8 * 7);
174+
#if defined(__x86_64__ ) || defined(__i386__)
175+
SHA3_ASSERT(memcmp(&t, buf, 8) == 0);
176+
#endif
177+
ctx->u.s[ctx->wordIndex] ^= t;
178+
if (++ctx->wordIndex ==
179+
(SHA3_KECCAK_SPONGE_WORDS - SHA3_CW(ctx->capacityWords))) {
180+
keccakf(ctx->u.s);
181+
ctx->wordIndex = 0;
182+
}
183+
}
184+
185+
/* finally, save the partial word */
186+
SHA3_ASSERT(ctx->byteIndex == 0 && tail < 8);
187+
while (tail--) {
188+
ctx->saved |= (uint64_t) (*(buf++)) << ((ctx->byteIndex++) * 8);
189+
}
190+
SHA3_ASSERT(ctx->byteIndex < 8);
191+
}
192+
193+
/* This is simply the 'update' with the padding block.
194+
* The padding block is 0x01 || 0x00* || 0x80. First 0x01 and last 0x80
195+
* bytes are always present, but they can be the same byte.
196+
*/
197+
void SHA3_Final(void *res, SHA3_CTX * ctx)
198+
{
199+
/* Append 2-bit suffix 01, per SHA-3 spec. Instead of 1 for padding we
200+
* use 1<<2 below. The 0x02 below corresponds to the suffix 01.
201+
* Overall, we feed 0, then 1, and finally 1 to start padding. Without
202+
* M || 01, we would simply use 1 to start padding. */
203+
204+
uint64_t t;
205+
206+
/* SHA3 version */
207+
t = (uint64_t) (((uint64_t) (0x02 | (1 << 2))) <<
208+
((ctx->byteIndex) * 8));
209+
210+
ctx->u.s[ctx->wordIndex] ^= ctx->saved ^ t;
211+
212+
ctx->u.s[SHA3_KECCAK_SPONGE_WORDS - SHA3_CW(ctx->capacityWords) - 1] ^=
213+
SHA3_CONST(0x8000000000000000UL);
214+
keccakf(ctx->u.s);
215+
216+
/* Return first bytes of the ctx->s. This conversion is not needed for
217+
* little-endian platforms e.g. wrap with #if !defined(__BYTE_ORDER__)
218+
* || !defined(__ORDER_LITTLE_ENDIAN__) || __BYTE_ORDER__!=__ORDER_LITTLE_ENDIAN__
219+
* ... the conversion below ...
220+
* #endif */
221+
{
222+
unsigned i;
223+
for (i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
224+
const unsigned t1 = (uint32_t) ctx->u.s[i];
225+
const unsigned t2 =
226+
(uint32_t) ((ctx->u.s[i] >> 16) >> 16);
227+
ctx->u.sb[i * 8 + 0] = (uint8_t) (t1);
228+
ctx->u.sb[i * 8 + 1] = (uint8_t) (t1 >> 8);
229+
ctx->u.sb[i * 8 + 2] = (uint8_t) (t1 >> 16);
230+
ctx->u.sb[i * 8 + 3] = (uint8_t) (t1 >> 24);
231+
ctx->u.sb[i * 8 + 4] = (uint8_t) (t2);
232+
ctx->u.sb[i * 8 + 5] = (uint8_t) (t2 >> 8);
233+
ctx->u.sb[i * 8 + 6] = (uint8_t) (t2 >> 16);
234+
ctx->u.sb[i * 8 + 7] = (uint8_t) (t2 >> 24);
235+
}
236+
}
237+
238+
memcpy(res, ctx->u.sb, ctx->digest_length/8);
239+
}

C/hashes/sha3.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
/**
3+
* Canonical implementation of Init/Update/Finalize for SHA-3 byte input.
4+
* Based on code from https://github.com/brainhub/SHA3IUF/
5+
*
6+
* This work is released into the public domain with CC0 1.0.
7+
*
8+
* Copyright (c) 2015. Andrey Jivsov <[email protected]>
9+
* Copyright (c) 2023 Tino Reichardt <[email protected]>
10+
*/
11+
12+
#ifndef SHA3_H
13+
#define SHA3_H
14+
15+
#include <stdint.h>
16+
17+
#define SHA3_256_DIGEST_LENGTH 32
18+
#define SHA3_384_DIGEST_LENGTH 48
19+
#define SHA3_512_DIGEST_LENGTH 64
20+
21+
/* 'Words' here refers to uint64_t */
22+
#define SHA3_KECCAK_SPONGE_WORDS (200 / sizeof(uint64_t))
23+
typedef struct sha3_context_ {
24+
/* the portion of the input message that we didn't consume yet */
25+
uint64_t saved;
26+
uint64_t byteIndex; /* 0..7--the next byte after the set one */
27+
uint64_t wordIndex; /* 0..24--the next word to integrate input */
28+
uint64_t capacityWords; /* the double size of the hash output in words */
29+
30+
/* Keccak's state */
31+
union {
32+
uint64_t s[SHA3_KECCAK_SPONGE_WORDS];
33+
uint8_t sb[SHA3_KECCAK_SPONGE_WORDS * 8];
34+
} u;
35+
36+
unsigned digest_length;
37+
} SHA3_CTX;
38+
39+
void SHA3_Init(SHA3_CTX * ctx, unsigned bitSize);
40+
void SHA3_Update(SHA3_CTX * ctx, void const *bufIn, size_t len);
41+
void SHA3_Final(void *, SHA3_CTX * ctx);
42+
43+
#endif

C/hashes/sha512.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

22
/*
3+
* Taken from lib/crypto/* of samba-4.5.8.tar.gz.
4+
*
35
* Copyright (c) 2006, 2010 Kungliga Tekniska Högskolan
46
* (Royal Institute of Technology, Stockholm, Sweden).
57
* All rights reserved.
@@ -32,8 +34,7 @@
3234
* SUCH DAMAGE.
3335
*/
3436

35-
#include "hash.h"
36-
#include "sha.h"
37+
#include "sha512.h"
3738

3839
#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
3940
#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))

0 commit comments

Comments
 (0)