Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
keccak256.cpp
Go to the documentation of this file.
1/* sha3 - an implementation of Secure Hash Algorithm 3 (Keccak).
2 * based on the
3 * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011
4 * by Guido Bertoni, Joan Daemen, Michaƫl Peeters and Gilles Van Assche
5 *
6 * Copyright: 2013 Aleksey Kravchenko <rhash.admin@gmail.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
18 */
19
21#include <cstring>
22
23#define BLOCK_SIZE ((1600 - 256 * 2) / 8)
24
25#define I64(x) x##LL
26#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n))))
27#define le2me_64(x) (x)
28#define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0)))
29#define me64_to_le_str(to, from, length) memcpy((to), (from), (length))
30
31/* constants */
32
33//const uint8_t round_constant_info[] PROGMEM = {
34//const uint8_t constants[] PROGMEM = {
35const uint8_t constants[] = {
36
37 1, 26, 94, 112, 31, 33, 121, 85, 14, 12, 53, 38, 63, 79, 93, 83, 82, 72, 22, 102, 121, 88, 33, 116,
38//};
39
40//const uint8_t pi_transform[] PROGMEM = {
41 1, 6, 9, 22, 14, 20, 2, 12, 13, 19, 23, 15, 4, 24, 21, 8, 16, 5, 3, 18, 17, 11, 7, 10,
42//};
43
44//const uint8_t rhoTransforms[] PROGMEM = {
45 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14,
46};
47
48#define TYPE_ROUND_INFO 0
49#define TYPE_PI_TRANSFORM 24
50#define TYPE_RHO_TRANSFORM 48
51
52inline uint8_t getConstant(uint8_t type, uint8_t index) {
53 return constants[type + index];
54 //return pgm_read_byte(&constants[type + index]);
55}
56
57static inline uint64_t get_round_constant(uint8_t round) {
58 uint64_t result = 0;
59
60 //uint8_t roundInfo = pgm_read_byte(&round_constant_info[round]);
61 uint8_t roundInfo = getConstant(TYPE_ROUND_INFO, round);
62 if (roundInfo & (1 << 6)) { result |= ((uint64_t)1 << 63); }
63 if (roundInfo & (1 << 5)) { result |= ((uint64_t)1 << 31); }
64 if (roundInfo & (1 << 4)) { result |= ((uint64_t)1 << 15); }
65 if (roundInfo & (1 << 3)) { result |= ((uint64_t)1 << 7); }
66 if (roundInfo & (1 << 2)) { result |= ((uint64_t)1 << 3); }
67 if (roundInfo & (1 << 1)) { result |= ((uint64_t)1 << 1); }
68 if (roundInfo & (1 << 0)) { result |= ((uint64_t)1 << 0); }
69
70 return result;
71}
72
73
74/* Initializing a sha3 context for given number of output bits */
76 /* NB: The Keccak capacity parameter = bits * 2 */
77
78 std::memset(ctx, 0, sizeof(SHA3_CTX));
79}
80
81/* Keccak theta() transformation */
82inline static void keccak_theta(uint64_t *A) {
83 uint64_t C[5], D[5];
84
85 for (uint8_t i = 0; i < 5; i++) {
86 C[i] = A[i];
87 for (uint8_t j = 5; j < 25; j += 5) { C[i] ^= A[i + j]; }
88 }
89
90 for (uint8_t i = 0; i < 5; i++) {
91 D[i] = ROTL64(C[(i + 1) % 5], 1) ^ C[(i + 4) % 5];
92 }
93
94 for (uint8_t i = 0; i < 5; i++) {
95 //for (uint8_t j = 0; j < 25; j += 5) {
96 for (uint8_t j = 0; j < 25; j += 5) { A[i + j] ^= D[i]; }
97 }
98}
99
100
101/* Keccak pi() transformation */
102inline static void keccak_pi(uint64_t *A) {
103 uint64_t A1 = A[1];
104 //for (uint8_t i = 1; i < sizeof(pi_transform); i++) {
105 for (uint8_t i = 1; i < 24; i++) {
106 //A[pgm_read_byte(&pi_transform[i - 1])] = A[pgm_read_byte(&pi_transform[i])];
108 }
109 A[10] = A1;
110 /* note: A[ 0] is left as is */
111}
112
113/*
114ketch uses 30084 bytes (93%) of program storage space. Maximum is 32256 bytes.
115Global variables use 743 bytes (36%) of dynamic memory, leaving 1305 bytes for local variables. Maximum is 2048 bytes.
116*/
117/* Keccak chi() transformation */
118inline static void keccak_chi(uint64_t *A) {
119 for (uint8_t i = 0; i < 25; i += 5) {
120 uint64_t A0 = A[0 + i], A1 = A[1 + i];
121 A[0 + i] ^= ~A1 & A[2 + i];
122 A[1 + i] ^= ~A[2 + i] & A[3 + i];
123 A[2 + i] ^= ~A[3 + i] & A[4 + i];
124 A[3 + i] ^= ~A[4 + i] & A0;
125 A[4 + i] ^= ~A0 & A1;
126 }
127}
128
129inline static void sha3_permutation(uint64_t *state) {
130 //for (uint8_t round = 0; round < sizeof(round_constant_info); round++) {
131 for (uint8_t round = 0; round < 24; round++) {
132 keccak_theta(state);
133
134 /* apply Keccak rho() transformation */
135 for (uint8_t i = 1; i < 25; i++) {
136 //state[i] = ROTL64(state[i], pgm_read_byte(&rhoTransforms[i - 1]));
138 }
139
140 keccak_pi(state);
141 keccak_chi(state);
142
143 /* apply iota(state, round) */
144 *state ^= get_round_constant(round);
145 }
146}
147
155inline static void sha3_process_block(uint64_t hash[25], const uint64_t *block) {
156 for (uint8_t i = 0; i < 17; i++) {
157 hash[i] ^= le2me_64(block[i]);
158 }
159
160 /* make a permutation of the hash */
161 sha3_permutation(hash);
162}
163
164//#define SHA3_FINALIZED 0x80000000
165//#define SHA3_FINALIZED 0x8000
166
175void keccak_update(SHA3_CTX *ctx, const unsigned char *msg, uint16_t size)
176{
177 uint16_t idx = (uint16_t)ctx->rest;
178
179 //if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */
180 ctx->rest = (unsigned)((ctx->rest + size) % BLOCK_SIZE);
181
182 /* fill partial block */
183 if (idx) {
184 uint16_t left = BLOCK_SIZE - idx;
185 memcpy((char*)ctx->message + idx, msg, (size < left ? size : left));
186 if (size < left) return;
187
188 /* process partial block */
189 sha3_process_block(ctx->hash, ctx->message);
190 msg += left;
191 size -= left;
192 }
193
194 while (size >= BLOCK_SIZE) {
195 uint64_t* aligned_message_block;
196 if (IS_ALIGNED_64(msg)) {
197 // the most common case is processing of an already aligned message without copying it
198 aligned_message_block = (uint64_t*)(void*)msg;
199 } else {
200 memcpy(ctx->message, msg, BLOCK_SIZE);
201 aligned_message_block = ctx->message;
202 }
203
204 sha3_process_block(ctx->hash, aligned_message_block);
205 msg += BLOCK_SIZE;
206 size -= BLOCK_SIZE;
207 }
208
209 if (size) {
210 memcpy(ctx->message, msg, size); /* save leftovers */
211 }
212}
213
220void keccak_final(SHA3_CTX *ctx, unsigned char* result)
221{
223
224// if (!(ctx->rest & SHA3_FINALIZED)) {
225 /* clear the rest of the data queue */
226 memset((char*)ctx->message + ctx->rest, 0, BLOCK_SIZE - ctx->rest);
227 ((char*)ctx->message)[ctx->rest] |= 0x01;
228 ((char*)ctx->message)[BLOCK_SIZE - 1] |= 0x80;
229
230 /* process final block */
231 sha3_process_block(ctx->hash, ctx->message);
232// ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
233// }
234
235 if (result) {
236 me64_to_le_str(result, ctx->hash, digest_length);
237 }
238}
#define D(var, file, col, who, lev,...)
Definition debug.h:44
void keccak_init(SHA3_CTX *ctx)
Definition keccak256.cpp:75
#define IS_ALIGNED_64(p)
Definition keccak256.cpp:28
#define me64_to_le_str(to, from, length)
Definition keccak256.cpp:29
void keccak_update(SHA3_CTX *ctx, const unsigned char *msg, uint16_t size)
#define TYPE_ROUND_INFO
Definition keccak256.cpp:48
const uint8_t constants[]
Definition keccak256.cpp:35
#define le2me_64(x)
Definition keccak256.cpp:27
void keccak_final(SHA3_CTX *ctx, unsigned char *result)
uint8_t getConstant(uint8_t type, uint8_t index)
Definition keccak256.cpp:52
#define TYPE_PI_TRANSFORM
Definition keccak256.cpp:49
#define TYPE_RHO_TRANSFORM
Definition keccak256.cpp:50
#define BLOCK_SIZE
Definition keccak256.cpp:23
#define ROTL64(qword, n)
Definition keccak256.cpp:26
unsigned short uint16_t
Definition stdint.h:125
unsigned char uint8_t
Definition stdint.h:124
unsigned __int64 uint64_t
Definition stdint.h:136
uint16_t rest
Definition keccak256.hpp:37
uint64_t message[sha3_max_rate_in_qwords]
Definition keccak256.hpp:35
uint64_t hash[sha3_max_permutation_size]
Definition keccak256.hpp:33
uint16_t j
CK_ULONG digest_length
memset(pInfo->slotDescription, ' ', 64)
memcpy((char *) pInfo->slotDescription, s, l)