1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
6 * The library is free for all purposes without any express
10 /* based on https://github.com/brainhub/SHA3IUF (public domain) */
16 const struct ltc_hash_descriptor sha3_224_desc =
18 "sha3-224", /* name of hash */
20 28, /* Size of digest in octets */
21 144, /* Input block size in octets */
22 { 2,16,840,1,101,3,4,2,7 }, /* ASN.1 OID */
31 const struct ltc_hash_descriptor sha3_256_desc =
33 "sha3-256", /* name of hash */
35 32, /* Size of digest in octets */
36 136, /* Input block size in octets */
37 { 2,16,840,1,101,3,4,2,8 }, /* ASN.1 OID */
46 const struct ltc_hash_descriptor sha3_384_desc =
48 "sha3-384", /* name of hash */
50 48, /* Size of digest in octets */
51 104, /* Input block size in octets */
52 { 2,16,840,1,101,3,4,2,9 }, /* ASN.1 OID */
61 const struct ltc_hash_descriptor sha3_512_desc =
63 "sha3-512", /* name of hash */
65 64, /* Size of digest in octets */
66 72, /* Input block size in octets */
67 { 2,16,840,1,101,3,4,2,10 }, /* ASN.1 OID */
76 #define SHA3_KECCAK_SPONGE_WORDS 25 /* 1600 bits > 200 bytes > 25 x ulong64 */
77 #define SHA3_KECCAK_ROUNDS 24
79 static const ulong64 keccakf_rndc[24] = {
80 CONST64(0x0000000000000001), CONST64(0x0000000000008082),
81 CONST64(0x800000000000808a), CONST64(0x8000000080008000),
82 CONST64(0x000000000000808b), CONST64(0x0000000080000001),
83 CONST64(0x8000000080008081), CONST64(0x8000000000008009),
84 CONST64(0x000000000000008a), CONST64(0x0000000000000088),
85 CONST64(0x0000000080008009), CONST64(0x000000008000000a),
86 CONST64(0x000000008000808b), CONST64(0x800000000000008b),
87 CONST64(0x8000000000008089), CONST64(0x8000000000008003),
88 CONST64(0x8000000000008002), CONST64(0x8000000000000080),
89 CONST64(0x000000000000800a), CONST64(0x800000008000000a),
90 CONST64(0x8000000080008081), CONST64(0x8000000000008080),
91 CONST64(0x0000000080000001), CONST64(0x8000000080008008)
94 static const unsigned keccakf_rotc[24] = {
95 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
98 static const unsigned keccakf_piln[24] = {
99 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
102 static void keccakf(ulong64 s[25])
107 for(round = 0; round < SHA3_KECCAK_ROUNDS; round++) {
109 for(i = 0; i < 5; i++)
110 bc[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
112 for(i = 0; i < 5; i++) {
113 t = bc[(i + 4) % 5] ^ ROL64(bc[(i + 1) % 5], 1);
114 for(j = 0; j < 25; j += 5)
119 for(i = 0; i < 24; i++) {
122 s[j] = ROL64(t, keccakf_rotc[i]);
126 for(j = 0; j < 25; j += 5) {
127 for(i = 0; i < 5; i++)
129 for(i = 0; i < 5; i++)
130 s[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
133 s[0] ^= keccakf_rndc[round];
137 /* Public Inteface */
139 int sha3_224_init(hash_state *md)
141 LTC_ARGCHK(md != NULL);
142 XMEMSET(&md->sha3, 0, sizeof(md->sha3));
143 md->sha3.capacity_words = 2 * 224 / (8 * sizeof(ulong64));
147 int sha3_256_init(hash_state *md)
149 LTC_ARGCHK(md != NULL);
150 XMEMSET(&md->sha3, 0, sizeof(md->sha3));
151 md->sha3.capacity_words = 2 * 256 / (8 * sizeof(ulong64));
155 int sha3_384_init(hash_state *md)
157 LTC_ARGCHK(md != NULL);
158 XMEMSET(&md->sha3, 0, sizeof(md->sha3));
159 md->sha3.capacity_words = 2 * 384 / (8 * sizeof(ulong64));
163 int sha3_512_init(hash_state *md)
165 LTC_ARGCHK(md != NULL);
166 XMEMSET(&md->sha3, 0, sizeof(md->sha3));
167 md->sha3.capacity_words = 2 * 512 / (8 * sizeof(ulong64));
171 int sha3_shake_init(hash_state *md, int num)
173 LTC_ARGCHK(md != NULL);
174 if (num != 128 && num != 256) return CRYPT_INVALID_ARG;
175 XMEMSET(&md->sha3, 0, sizeof(md->sha3));
176 md->sha3.capacity_words = (unsigned short)(2 * num / (8 * sizeof(ulong64)));
180 int sha3_process(hash_state *md, const unsigned char *in, unsigned long inlen)
182 /* 0...7 -- how much is needed to have a word */
183 unsigned old_tail = (8 - md->sha3.byte_index) & 7;
189 if (inlen == 0) return CRYPT_OK; /* nothing to do */
190 LTC_ARGCHK(md != NULL);
191 LTC_ARGCHK(in != NULL);
193 if(inlen < old_tail) { /* have no complete word or haven't started the word yet */
194 while (inlen--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
198 if(old_tail) { /* will have one word to process */
200 while (old_tail--) md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
201 /* now ready to add saved to the sponge */
202 md->sha3.s[md->sha3.word_index] ^= md->sha3.saved;
203 md->sha3.byte_index = 0;
205 if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) {
207 md->sha3.word_index = 0;
211 /* now work in full words directly from input */
212 words = inlen / sizeof(ulong64);
213 tail = inlen - words * sizeof(ulong64);
215 for(i = 0; i < words; i++, in += sizeof(ulong64)) {
218 md->sha3.s[md->sha3.word_index] ^= t;
219 if(++md->sha3.word_index == (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words)) {
221 md->sha3.word_index = 0;
225 /* finally, save the partial word */
227 md->sha3.saved |= (ulong64) (*(in++)) << ((md->sha3.byte_index++) * 8);
232 int sha3_done(hash_state *md, unsigned char *hash)
236 LTC_ARGCHK(md != NULL);
237 LTC_ARGCHK(hash != NULL);
239 md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (CONST64(0x06) << (md->sha3.byte_index * 8)));
240 md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000);
243 /* store sha3.s[] as little-endian bytes into sha3.sb */
244 for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
245 STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
248 XMEMCPY(hash, md->sha3.sb, md->sha3.capacity_words * 4);
252 int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen)
254 /* IMPORTANT NOTE: sha3_shake_done can be called many times */
258 if (outlen == 0) return CRYPT_OK; /* nothing to do */
259 LTC_ARGCHK(md != NULL);
260 LTC_ARGCHK(out != NULL);
262 if (!md->sha3.xof_flag) {
263 /* shake_xof operation must be done only once */
264 md->sha3.s[md->sha3.word_index] ^= (md->sha3.saved ^ (CONST64(0x1F) << (md->sha3.byte_index * 8)));
265 md->sha3.s[SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words - 1] ^= CONST64(0x8000000000000000);
267 /* store sha3.s[] as little-endian bytes into sha3.sb */
268 for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
269 STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
271 md->sha3.byte_index = 0;
272 md->sha3.xof_flag = 1;
275 for (idx = 0; idx < outlen; idx++) {
276 if(md->sha3.byte_index >= (SHA3_KECCAK_SPONGE_WORDS - md->sha3.capacity_words) * 8) {
278 /* store sha3.s[] as little-endian bytes into sha3.sb */
279 for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) {
280 STORE64L(md->sha3.s[i], md->sha3.sb + i * 8);
282 md->sha3.byte_index = 0;
284 out[idx] = md->sha3.sb[md->sha3.byte_index++];
289 int sha3_shake_memory(int num, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen)
293 LTC_ARGCHK(in != NULL);
294 LTC_ARGCHK(out != NULL);
295 LTC_ARGCHK(outlen != NULL);
296 if ((err = sha3_shake_init(&md, num)) != CRYPT_OK) return err;
297 if ((err = sha3_shake_process(&md, in, inlen)) != CRYPT_OK) return err;
298 if ((err = sha3_shake_done(&md, out, *outlen)) != CRYPT_OK) return err;
304 /* ref: $Format:%D$ */
305 /* git commit: $Format:%H$ */
306 /* commit time: $Format:%ai$ */