github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/mining/tensority/cgo_algorithm/lib/sha3-allInOne.h (about) 1 /* sha3-allInOne.h */ 2 #ifndef RHASH_SHA3_H 3 #define RHASH_SHA3_H 4 #include "ustd.h" 5 6 #ifdef __cplusplus 7 extern "C" { 8 #endif 9 10 #define sha3_224_hash_size 28 11 #define sha3_256_hash_size 32 12 #define sha3_384_hash_size 48 13 #define sha3_512_hash_size 64 14 #define sha3_max_permutation_size 25 15 #define sha3_max_rate_in_qwords 24 16 17 /** 18 * SHA3 Algorithm context. 19 */ 20 typedef struct sha3_ctx 21 { 22 /* 1600 bits algorithm hashing state */ 23 uint64_t hash[sha3_max_permutation_size]; 24 /* 1536-bit buffer for leftovers */ 25 uint64_t message[sha3_max_rate_in_qwords]; 26 /* count of bytes in the message[] buffer */ 27 unsigned rest; 28 /* size of a message block processed at once */ 29 unsigned block_size; 30 } sha3_ctx; 31 32 /* methods for calculating the hash function */ 33 34 // void rhash_sha3_224_init(sha3_ctx *ctx); 35 // void rhash_sha3_256_init(sha3_ctx *ctx); 36 // void rhash_sha3_384_init(sha3_ctx *ctx); 37 // void rhash_sha3_512_init(sha3_ctx *ctx); 38 // void rhash_sha3_update(sha3_ctx *ctx, const unsigned char* msg, size_t size); 39 // void rhash_sha3_final(sha3_ctx *ctx, unsigned char* result); 40 41 #ifdef USE_KECCAK 42 #define rhash_keccak_224_init rhash_sha3_224_init 43 #define rhash_keccak_256_init rhash_sha3_256_init 44 #define rhash_keccak_384_init rhash_sha3_384_init 45 #define rhash_keccak_512_init rhash_sha3_512_init 46 #define rhash_keccak_update rhash_sha3_update 47 inline void rhash_keccak_final(sha3_ctx *ctx, unsigned char* result); 48 #endif 49 50 #ifdef __cplusplus 51 } /* extern "C" */ 52 #endif /* __cplusplus */ 53 54 55 56 // Adpated from sha3.c 57 /*--------------------------------------------------------------------------*/ 58 /* sha3.c - an implementation of Secure Hash Algorithm 3 (Keccak). 59 * based on the 60 * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 61 * by Guido Bertoni, Joan Daemen, Michaƫl Peeters and Gilles Van Assche 62 * 63 * Copyright: 2013 Aleksey Kravchenko <rhash.admin@gmail.com> 64 * 65 * Permission is hereby granted, free of charge, to any person obtaining a 66 * copy of this software and associated documentation files (the "Software"), 67 * to deal in the Software without restriction, including without limitation 68 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 69 * and/or sell copies of the Software, and to permit persons to whom the 70 * Software is furnished to do so. 71 * 72 * This program is distributed in the hope that it will be useful, but 73 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 74 * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk! 75 */ 76 77 #include <assert.h> 78 #include <string.h> 79 #include "byte_order-allInOne.h" 80 81 /* constants */ 82 #define NumberOfRounds 24 83 84 /* SHA3 (Keccak) constants for 24 rounds */ 85 static uint64_t keccak_round_constants[NumberOfRounds] = { 86 I64(0x0000000000000001), I64(0x0000000000008082), I64(0x800000000000808A), I64(0x8000000080008000), 87 I64(0x000000000000808B), I64(0x0000000080000001), I64(0x8000000080008081), I64(0x8000000000008009), 88 I64(0x000000000000008A), I64(0x0000000000000088), I64(0x0000000080008009), I64(0x000000008000000A), 89 I64(0x000000008000808B), I64(0x800000000000008B), I64(0x8000000000008089), I64(0x8000000000008003), 90 I64(0x8000000000008002), I64(0x8000000000000080), I64(0x000000000000800A), I64(0x800000008000000A), 91 I64(0x8000000080008081), I64(0x8000000000008080), I64(0x0000000080000001), I64(0x8000000080008008) 92 }; 93 94 /* Initializing a sha3 context for given number of output bits */ 95 inline void rhash_keccak_init(sha3_ctx *ctx, unsigned bits) 96 { 97 /* NB: The Keccak capacity parameter = bits * 2 */ 98 unsigned rate = 1600 - bits * 2; 99 100 memset(ctx, 0, sizeof(sha3_ctx)); 101 ctx->block_size = rate / 8; 102 assert(rate <= 1600 && (rate % 64) == 0); 103 } 104 105 /** 106 * Initialize context before calculating hash. 107 * 108 * @param ctx context to initialize 109 */ 110 inline void rhash_sha3_224_init(sha3_ctx *ctx) 111 { 112 rhash_keccak_init(ctx, 224); 113 } 114 115 /** 116 * Initialize context before calculating hash. 117 * 118 * @param ctx context to initialize 119 */ 120 inline void rhash_sha3_256_init(sha3_ctx *ctx) 121 { 122 rhash_keccak_init(ctx, 256); 123 } 124 125 /** 126 * Initialize context before calculating hash. 127 * 128 * @param ctx context to initialize 129 */ 130 inline void rhash_sha3_384_init(sha3_ctx *ctx) 131 { 132 rhash_keccak_init(ctx, 384); 133 } 134 135 /** 136 * Initialize context before calculating hash. 137 * 138 * @param ctx context to initialize 139 */ 140 inline void rhash_sha3_512_init(sha3_ctx *ctx) 141 { 142 rhash_keccak_init(ctx, 512); 143 } 144 145 /* Keccak theta() transformation */ 146 inline void keccak_theta(uint64_t *A) 147 { 148 unsigned int x; 149 uint64_t C[5], D[5]; 150 151 for (x = 0; x < 5; x++) { 152 C[x] = A[x] ^ A[x + 5] ^ A[x + 10] ^ A[x + 15] ^ A[x + 20]; 153 } 154 D[0] = ROTL64(C[1], 1) ^ C[4]; 155 D[1] = ROTL64(C[2], 1) ^ C[0]; 156 D[2] = ROTL64(C[3], 1) ^ C[1]; 157 D[3] = ROTL64(C[4], 1) ^ C[2]; 158 D[4] = ROTL64(C[0], 1) ^ C[3]; 159 160 for (x = 0; x < 5; x++) { 161 A[x] ^= D[x]; 162 A[x + 5] ^= D[x]; 163 A[x + 10] ^= D[x]; 164 A[x + 15] ^= D[x]; 165 A[x + 20] ^= D[x]; 166 } 167 } 168 169 /* Keccak pi() transformation */ 170 inline void keccak_pi(uint64_t *A) 171 { 172 uint64_t A1; 173 A1 = A[1]; 174 A[ 1] = A[ 6]; 175 A[ 6] = A[ 9]; 176 A[ 9] = A[22]; 177 A[22] = A[14]; 178 A[14] = A[20]; 179 A[20] = A[ 2]; 180 A[ 2] = A[12]; 181 A[12] = A[13]; 182 A[13] = A[19]; 183 A[19] = A[23]; 184 A[23] = A[15]; 185 A[15] = A[ 4]; 186 A[ 4] = A[24]; 187 A[24] = A[21]; 188 A[21] = A[ 8]; 189 A[ 8] = A[16]; 190 A[16] = A[ 5]; 191 A[ 5] = A[ 3]; 192 A[ 3] = A[18]; 193 A[18] = A[17]; 194 A[17] = A[11]; 195 A[11] = A[ 7]; 196 A[ 7] = A[10]; 197 A[10] = A1; 198 /* note: A[ 0] is left as is */ 199 } 200 201 /* Keccak chi() transformation */ 202 inline void keccak_chi(uint64_t *A) 203 { 204 int i; 205 for (i = 0; i < 25; i += 5) { 206 uint64_t A0 = A[0 + i], A1 = A[1 + i]; 207 A[0 + i] ^= ~A1 & A[2 + i]; 208 A[1 + i] ^= ~A[2 + i] & A[3 + i]; 209 A[2 + i] ^= ~A[3 + i] & A[4 + i]; 210 A[3 + i] ^= ~A[4 + i] & A0; 211 A[4 + i] ^= ~A0 & A1; 212 } 213 } 214 215 inline void rhash_sha3_permutation(uint64_t *state) 216 { 217 int round; 218 for (round = 0; round < NumberOfRounds; round++) 219 { 220 keccak_theta(state); 221 222 /* apply Keccak rho() transformation */ 223 state[ 1] = ROTL64(state[ 1], 1); 224 state[ 2] = ROTL64(state[ 2], 62); 225 state[ 3] = ROTL64(state[ 3], 28); 226 state[ 4] = ROTL64(state[ 4], 27); 227 state[ 5] = ROTL64(state[ 5], 36); 228 state[ 6] = ROTL64(state[ 6], 44); 229 state[ 7] = ROTL64(state[ 7], 6); 230 state[ 8] = ROTL64(state[ 8], 55); 231 state[ 9] = ROTL64(state[ 9], 20); 232 state[10] = ROTL64(state[10], 3); 233 state[11] = ROTL64(state[11], 10); 234 state[12] = ROTL64(state[12], 43); 235 state[13] = ROTL64(state[13], 25); 236 state[14] = ROTL64(state[14], 39); 237 state[15] = ROTL64(state[15], 41); 238 state[16] = ROTL64(state[16], 45); 239 state[17] = ROTL64(state[17], 15); 240 state[18] = ROTL64(state[18], 21); 241 state[19] = ROTL64(state[19], 8); 242 state[20] = ROTL64(state[20], 18); 243 state[21] = ROTL64(state[21], 2); 244 state[22] = ROTL64(state[22], 61); 245 state[23] = ROTL64(state[23], 56); 246 state[24] = ROTL64(state[24], 14); 247 248 keccak_pi(state); 249 keccak_chi(state); 250 251 /* apply iota(state, round) */ 252 *state ^= keccak_round_constants[round]; 253 } 254 } 255 256 /** 257 * The core transformation. Process the specified block of data. 258 * 259 * @param hash the algorithm state 260 * @param block the message block to process 261 * @param block_size the size of the processed block in bytes 262 */ 263 inline void rhash_sha3_process_block(uint64_t hash[25], const uint64_t *block, size_t block_size) 264 { 265 /* expanded loop */ 266 hash[ 0] ^= le2me_64(block[ 0]); 267 hash[ 1] ^= le2me_64(block[ 1]); 268 hash[ 2] ^= le2me_64(block[ 2]); 269 hash[ 3] ^= le2me_64(block[ 3]); 270 hash[ 4] ^= le2me_64(block[ 4]); 271 hash[ 5] ^= le2me_64(block[ 5]); 272 hash[ 6] ^= le2me_64(block[ 6]); 273 hash[ 7] ^= le2me_64(block[ 7]); 274 hash[ 8] ^= le2me_64(block[ 8]); 275 /* if not sha3-512 */ 276 if (block_size > 72) { 277 hash[ 9] ^= le2me_64(block[ 9]); 278 hash[10] ^= le2me_64(block[10]); 279 hash[11] ^= le2me_64(block[11]); 280 hash[12] ^= le2me_64(block[12]); 281 /* if not sha3-384 */ 282 if (block_size > 104) { 283 hash[13] ^= le2me_64(block[13]); 284 hash[14] ^= le2me_64(block[14]); 285 hash[15] ^= le2me_64(block[15]); 286 hash[16] ^= le2me_64(block[16]); 287 /* if not sha3-256 */ 288 if (block_size > 136) { 289 hash[17] ^= le2me_64(block[17]); 290 #ifdef FULL_SHA3_FAMILY_SUPPORT 291 /* if not sha3-224 */ 292 if (block_size > 144) { 293 hash[18] ^= le2me_64(block[18]); 294 hash[19] ^= le2me_64(block[19]); 295 hash[20] ^= le2me_64(block[20]); 296 hash[21] ^= le2me_64(block[21]); 297 hash[22] ^= le2me_64(block[22]); 298 hash[23] ^= le2me_64(block[23]); 299 hash[24] ^= le2me_64(block[24]); 300 } 301 #endif 302 } 303 } 304 } 305 /* make a permutation of the hash */ 306 rhash_sha3_permutation(hash); 307 } 308 309 #define SHA3_FINALIZED 0x80000000 310 311 /** 312 * Calculate message hash. 313 * Can be called repeatedly with chunks of the message to be hashed. 314 * 315 * @param ctx the algorithm context containing current hashing state 316 * @param msg message chunk 317 * @param size length of the message chunk 318 */ 319 inline void rhash_sha3_update(sha3_ctx *ctx, const unsigned char *msg, size_t size) 320 { 321 size_t index = (size_t)ctx->rest; 322 size_t block_size = (size_t)ctx->block_size; 323 324 if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */ 325 ctx->rest = (unsigned)((ctx->rest + size) % block_size); 326 327 /* fill partial block */ 328 if (index) { 329 size_t left = block_size - index; 330 memcpy((char*)ctx->message + index, msg, (size < left ? size : left)); 331 if (size < left) return; 332 333 /* process partial block */ 334 rhash_sha3_process_block(ctx->hash, ctx->message, block_size); 335 msg += left; 336 size -= left; 337 } 338 while (size >= block_size) { 339 uint64_t* aligned_message_block; 340 if (IS_ALIGNED_64(msg)) { 341 /* the most common case is processing of an already aligned message 342 without copying it */ 343 aligned_message_block = (uint64_t*)msg; 344 } else { 345 memcpy(ctx->message, msg, block_size); 346 aligned_message_block = ctx->message; 347 } 348 349 rhash_sha3_process_block(ctx->hash, aligned_message_block, block_size); 350 msg += block_size; 351 size -= block_size; 352 } 353 if (size) { 354 memcpy(ctx->message, msg, size); /* save leftovers */ 355 } 356 } 357 358 /** 359 * Store calculated hash into the given array. 360 * 361 * @param ctx the algorithm context containing current hashing state 362 * @param result calculated hash in binary form 363 */ 364 inline void rhash_sha3_final(sha3_ctx *ctx, unsigned char* result) 365 { 366 size_t digest_length = 100 - ctx->block_size / 2; 367 const size_t block_size = ctx->block_size; 368 369 if (!(ctx->rest & SHA3_FINALIZED)) 370 { 371 /* clear the rest of the data queue */ 372 memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest); 373 ((char*)ctx->message)[ctx->rest] |= 0x06; 374 ((char*)ctx->message)[block_size - 1] |= 0x80; 375 376 /* process final block */ 377 rhash_sha3_process_block(ctx->hash, ctx->message, block_size); 378 ctx->rest = SHA3_FINALIZED; /* mark context as finalized */ 379 } 380 381 assert(block_size > digest_length); 382 if (result) me64_to_le_str(result, ctx->hash, digest_length); 383 } 384 385 #ifdef USE_KECCAK 386 /** 387 * Store calculated hash into the given array. 388 * 389 * @param ctx the algorithm context containing current hashing state 390 * @param result calculated hash in binary form 391 */ 392 inline void rhash_keccak_final(sha3_ctx *ctx, unsigned char* result) 393 { 394 size_t digest_length = 100 - ctx->block_size / 2; 395 const size_t block_size = ctx->block_size; 396 397 if (!(ctx->rest & SHA3_FINALIZED)) 398 { 399 /* clear the rest of the data queue */ 400 memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest); 401 ((char*)ctx->message)[ctx->rest] |= 0x01; 402 ((char*)ctx->message)[block_size - 1] |= 0x80; 403 404 /* process final block */ 405 rhash_sha3_process_block(ctx->hash, ctx->message, block_size); 406 ctx->rest = SHA3_FINALIZED; /* mark context as finalized */ 407 } 408 409 assert(block_size > digest_length); 410 if (result) me64_to_le_str(result, ctx->hash, digest_length); 411 } 412 #endif /* USE_KECCAK */ 413 414 415 416 #endif /* RHASH_SHA3_H */