1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-02-12 11:12:16 +00:00
ton/crypto/keccak/keccak.cpp
EmelyanenkoK 9f93888cf4
TVM Upgrade (#686)
* New TVM instructions

* Remove PREVBLOCKS

* Separate target ton_crypto into TVM-related and -unrelared code

* Add fine for failed "send message"; rework SENDMSG

* Fix include

* Fix bugs, improve action fines

* Disable fines for special accounts

* Handle msg_balance_remaining.grams == null in transaction.cpp

* Bugfixes in SENDMSG

* Fix fee calculation in SENDMSG

* Fix CellStorageStat and transaction.cpp after merge

* SETBOUNCEONACTIONPHASEFAIL instruction

* ADDDIVMOD instructions

* RUNVM, RUNVMX instructions

* Changes in RUNVM

* Tests for adddiv and runvm

* HASHEXT instruction

* Improve opcode-timing

More iterations
Don't measure preliminary run
Remove logs and other excessive operations
Add "error" to output

* Increase RUNVM gas price

* Optimize HASHEXT, adjust gas price

* Add "bounce of action fail" flag to actions

* Stack operations with unlimited arguments

* Ristretto255 instructions

* Adjust gas consumption

* Optional fixed number of return values in RUNVM, fix exception handling

* Adjust gas consumption

* Simplify gas consumption logic

* Support of secp256k1 and sodium libraries in builds (#11)

* add support of secp256k1 library to the builds (linux, win)

* add support of secp256k1 library to the builds (linux, win)

* install secp256k1 via brew

* install libsodium via brew;
change sodium to upper case in FindSodium.cmake

* install libsodium via brew;
change sodium to upper case in FindSodium.cmake

* simplify FindSodium.cmake

* bug fixing

* bug fixing

* bug fixing

* add macro SODIUM_STATIC

* adjust build command for windows

* put back original FindSodium.cmake

* put back original FindSodium.cmake

* fix sodium unzipped path for windows;
add ninja

* fix sodium unzipped path for windows;
add ninja

* fix sodium unzipped path for windows;
add ninja

* Win32 github build for secp256k1

* x64 architecture github build for secp256k1

* fix sodium linking on linux

* enable docker buildx arm64 builds from forked repos

* enable docker buildx arm64 builds from forked repos

* enable docker buildx arm64 builds from forked repos

* adjust mac builds for secp2561k and sodium

* fix tonlib jni generation

* minor fix

* sync fixes across platforms

* add libsodium build script for android and precompiled static libraries

* build tonlib for android (fails)

* FindSodium uppercase

* remove system libsodium for android, use precompiled instead;
specify SECP256K1_INCLUDE_DIR fir mac 12.6

* uppercase sodium

* simplify FindSodium

* fix windows build sodium path;
use ninja for windows

* simplify sodium 2

* adjust windows sodium paths;
add paths to android jni

* add ninja build windows

* add ninja build windows

* add ninja build windows 2

* remove win ninja

* fix 1

* fix 2

* fix win 3

* fix linux compile 3

* fix jni 1

* fix jni 2 and mac

* fix jni 3

* fix jni 4

* fix jni 5

* fix mac 6

* fix mac 7 and jni paths

* fix jni 8

* rework sodium for android

* rework sodium for android

* rework sodium for android 2

* fixed sodium for android 2

* fixed sodium for android 3

* static secp256k1 for android

* add precompiled arm secp256k1

* add precompiled arm secp256k1

* build native-lib with secp256k1 x86-64 (non arm)

* update precompiled with NDK libsecp256k1.a

* update precompiled with NDK libsecp256k1.a

* update precompiled with NDK libsecp256k1.a

* refactor llvm-strip location

* refactor llvm-strip location

* add native-lib.so for armv7a, armv8a

* add native-lib.so for armv7a, armv8a

* test  armv7a, armv8a

* armv7a - fails linking on sodium, test -> armv8a

* works x86-64, armv7a - fails linking on sodium, armv8a - fails linking secp256k1 (incompatible with aarch64linux)

* update libpsec256k1, sodium static libs

* test x86 android native-lib

* test armv7 android native-lib

* test armv8 android native-lib

* x86_64 and arm64 android native-lib works

* x86_64 and arm64 android native-lib works

* x86_64 and arm64 android native-lib works

* test armv7 android native-lib

* test all android native-libs

* test all android native-libs

* test all android native-libs

* test all android native-libs - without SodiumAndroid

* test all android native-libs - with FindSodiumAndroid.cmake

* win, with Sodium via SODIUM_DIR

* win, with Sodium via SODIUM_DIR env

* win, with Sodium via SODIUM_DIR env

* win, with Sodium via SODIUM_DIR env and SODIUM_USE_STATIC_LIBS

* win, with Sodium via SODIUM_DIR, SODIUM_USE_STATIC_LIBS and SODIUM_INCLUDE_DIR

* android, with FindSodium

* android, with FindSodium with SODIUM_USE_STATIC_LIBS

* remove if not apple

* target_link_libraries(ton_crypto_core PUBLIC secp256k1)

* android SECP256K1_INCLUDE_DIRS

* android SECP256K1_INCLUDE_DIR

* add libsecp256k1.a/so pre-compiled with ubuntu 22 x86-64

* add libsecp256k1.a/so pre-compiled with ubuntu 22 x86-64

* sodium dirs

* sodium dirs

* sodium dirs

* remove NOT APPLE and SodiumAndroid

* add NOT APPLE and remove SodiumAndroid

* add NOT APPLE and remove SodiumAndroid

* remove build scripts for 18.04, reduce CMakeLists.txt

* remove build scripts for 18.04, reduce CMakeLists.txt

* Fix cas consumption during library load

* Fix fetch_config_params after merge

* Add all ADDDIVMOD ops to Asm.fif

* Save unpaid storage fee to due_payment

* Add "set prev blocks info" to emulator

* Adjusted builds  (#13)

* Update flake.nix

Add libsodium

* add libsecp256k1-dev and libsodium-dev into wasm build

* make back emulator a shared library;
put emulator to artifacts;
compile wasm artifacts with sodium and secp256k1.

* add secp256k1 to nix

* compile emulator statically with nix

* compile emulator statically with nix

* compile emulator lib statically with nix

* compile emulator lib statically with nix

* add libemulator to artifacts

* add shared libemulator library to artifacts

* minor release fix

* update set-output commands;
add recent_changelog.md

* releases fixes

* releases fixes, multiline

* releases fixes, multiline

* releases fixes, multiline

* put back multiline changelog

* put back multiline changelog

* ConfigParam 19 (global-id) and GLOBALID instruction

* Fix gas consumption in HASHEXT

* Add blst library

* Add bls instructions

* Allow passing long code to opcode-timing

* Add bls testcase

* More BLS instructions

* Fix tests, add bls tests

* Add more bls tests

* Improve some bls operations

* Adjust some BLS gas prices

* Adjust BLS gas prices

* Enable __BLST_PORTABLE__ flag only if PORTABLE flag is set

* Add tests for BLS_PAIRING

* GASCONSUMED instruction

* Fix compilation against docker with blst library; (#14)

* fix compilation against docker with blst library;
add precompiled libblst.a to android builds

* minor fix

* Adjust BLKSWX gas

* Fix comparison with NAN

* Allow arbitrary integers for scalars in ristretto multiplication, fix test

* Adjust nix builds according to PR 694 (#15)

* integrate and test PR-694

* integrate and test PR-694, test 2

* Add P256_CHKSIGN (secp256r1)

---------

Co-authored-by: SpyCheese <mikle98@yandex.ru>
Co-authored-by: neodiX42 <namlem@gmail.com>
2023-05-24 21:14:13 +03:00

473 lines
12 KiB
C++

/*
* An implementation of the SHA3 (Keccak) hash function family.
*
* Algorithm specifications: http://keccak.noekeon.org/
* NIST Announcement:
* http://csrc.nist.gov/groups/ST/hash/sha-3/winner_sha-3.html
*
* Written in 2013 by Fabrizio Tarizzo <fabrizio@fabriziotarizzo.org>
*
* ===================================================================
* The contents of this file are dedicated to the public domain. To
* the extent that dedication to the public domain is not available,
* everyone is granted a worldwide, perpetual, royalty-free,
* non-exclusive license to exercise all rights associated with the
* contents of this file for any purpose whatsoever.
* No rights are reserved.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* ===================================================================
*/
#include <string.h>
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#define KECCAK_F1600_STATE 200
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define MAX(x, y) ((x) < (y) ? (x) : (y))
/** Standard errors common to all ciphers **/
#define ERR_NULL 1
#define ERR_MEMORY 2
#define ERR_NOT_ENOUGH_DATA 3
#define ERR_ENCRYPT 4
#define ERR_DECRYPT 5
#define ERR_KEY_SIZE 6
#define ERR_NONCE_SIZE 7
#define ERR_NR_ROUNDS 8
#define ERR_DIGEST_SIZE 9
#define ERR_MAX_DATA 10
#define ERR_MAX_OFFSET 11
#define ERR_BLOCK_SIZE 12
#define ERR_TAG_SIZE 13
#define ERR_VALUE 14
#define ERR_EC_POINT 15
#define ERR_EC_CURVE 16
#define ERR_MODULUS 17
#define ERR_UNKNOWN 32
typedef struct
{
uint64_t state[25];
/* The buffer is as long as the state,
* but only 'rate' bytes will be used.
*/
uint8_t buf[KECCAK_F1600_STATE];
/* When absorbing, this is the number of bytes in buf that
* are coming from the message and outstanding.
* When squeezing, this is the remaining number of bytes
* that can be used as digest.
*/
unsigned valid_bytes;
/* All values in bytes */
unsigned capacity;
unsigned rate;
uint8_t squeezing;
uint8_t rounds;
} keccak_state;
#undef ROL64
#define ROL64(x,y) ((((x) << (y)) | (x) >> (64-(y))) & 0xFFFFFFFFFFFFFFFFULL)
static void keccak_function (uint64_t *state, unsigned rounds);
int keccak_reset(keccak_state *state)
{
if (NULL == state)
return ERR_NULL;
memset(state->state, 0, sizeof(state->state));
memset(state->buf, 0, sizeof(state->buf));
state->valid_bytes = 0;
state->squeezing = 0;
return 0;
}
static void keccak_absorb_internal (keccak_state *self)
{
unsigned i,j;
uint64_t d;
for (i=j=0; j < self->rate; ++i, j += 8) {
d = *(const uint64_t*)(self->buf + j);
self->state[i] ^= d;
}
}
static void
keccak_squeeze_internal (keccak_state *self)
{
unsigned i, j;
for (i=j=0; j < self->rate; ++i, j += 8) {
*(uint64_t*)(self->buf+j) = self->state[i];
}
}
int keccak_init (keccak_state **state,
size_t capacity_bytes,
uint8_t rounds)
{
keccak_state *ks;
if (NULL == state) {
return ERR_NULL;
}
*state = ks = (keccak_state*) calloc(1, sizeof(keccak_state));
if (NULL == ks)
return ERR_MEMORY;
if (capacity_bytes >= KECCAK_F1600_STATE)
return ERR_DIGEST_SIZE;
if ((rounds != 12) && (rounds != 24))
return ERR_NR_ROUNDS;
ks->capacity = (unsigned)capacity_bytes;
ks->rate = KECCAK_F1600_STATE - ks->capacity;
ks->squeezing = 0;
ks->rounds = rounds;
return 0;
}
int keccak_destroy(keccak_state *state)
{
free(state);
return 0;
}
int keccak_absorb (keccak_state *self,
const uint8_t *in,
size_t length)
{
if (NULL==self || NULL==in)
return ERR_NULL;
if (self->squeezing != 0)
return ERR_UNKNOWN;
while (length > 0) {
unsigned tc;
unsigned left;
left = self->rate - self->valid_bytes;
tc = (unsigned) MIN(length, left);
memcpy(self->buf + self->valid_bytes, in, tc);
self->valid_bytes += tc;
in += tc;
length -= tc;
if (self->valid_bytes == self->rate) {
keccak_absorb_internal (self);
keccak_function(self->state, self->rounds);
self->valid_bytes = 0;
}
}
return 0;
}
static void keccak_finish (keccak_state *self, uint8_t padding)
{
assert(self->squeezing == 0);
assert(self->valid_bytes < self->rate);
/* Padding */
memset(self->buf + self->valid_bytes, 0, self->rate - self->valid_bytes);
self->buf[self->valid_bytes] = padding;
self->buf[self->rate-1] |= 0x80;
/* Final absorb */
keccak_absorb_internal (self);
keccak_function (self->state, self->rounds);
/* First squeeze */
self->squeezing = 1;
keccak_squeeze_internal (self);
self->valid_bytes = self->rate;
}
int keccak_squeeze (keccak_state *self, uint8_t *out, size_t length, uint8_t padding)
{
if ((NULL == self) || (NULL == out))
return ERR_NULL;
if (self->squeezing == 0) {
keccak_finish (self, padding);
}
assert(self->squeezing == 1);
assert(self->valid_bytes > 0);
assert(self->valid_bytes <= self->rate);
while (length > 0) {
unsigned tc;
tc = (unsigned)MIN(self->valid_bytes, length);
memcpy(out, self->buf + (self->rate - self->valid_bytes), tc);
self->valid_bytes -= tc;
out += tc;
length -= tc;
if (self->valid_bytes == 0) {
keccak_function (self->state, self->rounds);
keccak_squeeze_internal (self);
self->valid_bytes = self->rate;
}
}
return 0;
}
int keccak_digest(keccak_state *state, uint8_t *digest, size_t len, uint8_t padding)
{
keccak_state tmp;
if ((NULL==state) || (NULL==digest))
return ERR_NULL;
if (2*len != state->capacity)
return ERR_UNKNOWN;
tmp = *state;
return keccak_squeeze(&tmp, digest, len, padding);
}
int keccak_copy(const keccak_state *src, keccak_state *dst)
{
if (NULL == src || NULL == dst) {
return ERR_NULL;
}
*dst = *src;
return 0;
}
/* Keccak core function */
#define KECCAK_ROUNDS 24
#define ROT_01 36
#define ROT_02 3
#define ROT_03 41
#define ROT_04 18
#define ROT_05 1
#define ROT_06 44
#define ROT_07 10
#define ROT_08 45
#define ROT_09 2
#define ROT_10 62
#define ROT_11 6
#define ROT_12 43
#define ROT_13 15
#define ROT_14 61
#define ROT_15 28
#define ROT_16 55
#define ROT_17 25
#define ROT_18 21
#define ROT_19 56
#define ROT_20 27
#define ROT_21 20
#define ROT_22 39
#define ROT_23 8
#define ROT_24 14
static const uint64_t roundconstants[KECCAK_ROUNDS] = {
0x0000000000000001ULL,
0x0000000000008082ULL,
0x800000000000808aULL,
0x8000000080008000ULL,
0x000000000000808bULL,
0x0000000080000001ULL,
0x8000000080008081ULL,
0x8000000000008009ULL,
0x000000000000008aULL,
0x0000000000000088ULL,
0x0000000080008009ULL,
0x000000008000000aULL,
0x000000008000808bULL,
0x800000000000008bULL,
0x8000000000008089ULL,
0x8000000000008003ULL,
0x8000000000008002ULL,
0x8000000000000080ULL,
0x000000000000800aULL,
0x800000008000000aULL,
0x8000000080008081ULL,
0x8000000000008080ULL,
0x0000000080000001ULL,
0x8000000080008008ULL
};
static void keccak_function (uint64_t *state, unsigned rounds)
{
unsigned i;
unsigned start_round;
/* Temporary variables to avoid indexing overhead */
uint64_t a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12;
uint64_t a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24;
uint64_t b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12;
uint64_t b13, b14, b15, b16, b17, b18, b19, b20, b21, b22, b23, b24;
uint64_t c0, c1, c2, c3, c4, d;
a0 = state[0];
a1 = state[1];
a2 = state[2];
a3 = state[3];
a4 = state[4];
a5 = state[5];
a6 = state[6];
a7 = state[7];
a8 = state[8];
a9 = state[9];
a10 = state[10];
a11 = state[11];
a12 = state[12];
a13 = state[13];
a14 = state[14];
a15 = state[15];
a16 = state[16];
a17 = state[17];
a18 = state[18];
a19 = state[19];
a20 = state[20];
a21 = state[21];
a22 = state[22];
a23 = state[23];
a24 = state[24];
if (rounds == 24)
start_round = 0;
else /* rounds == 12 */
start_round = 12;
for (i = start_round; i < KECCAK_ROUNDS; ++i) {
/*
Uses temporary variables and loop unrolling to
avoid array indexing and inner loops overhead
*/
/* Prepare column parity for Theta step */
c0 = a0 ^ a5 ^ a10 ^ a15 ^ a20;
c1 = a1 ^ a6 ^ a11 ^ a16 ^ a21;
c2 = a2 ^ a7 ^ a12 ^ a17 ^ a22;
c3 = a3 ^ a8 ^ a13 ^ a18 ^ a23;
c4 = a4 ^ a9 ^ a14 ^ a19 ^ a24;
/* Theta + Rho + Pi steps */
d = c4 ^ ROL64(c1, 1);
b0 = d ^ a0;
b16 = ROL64(d ^ a5, ROT_01);
b7 = ROL64(d ^ a10, ROT_02);
b23 = ROL64(d ^ a15, ROT_03);
b14 = ROL64(d ^ a20, ROT_04);
d = c0 ^ ROL64(c2, 1);
b10 = ROL64(d ^ a1, ROT_05);
b1 = ROL64(d ^ a6, ROT_06);
b17 = ROL64(d ^ a11, ROT_07);
b8 = ROL64(d ^ a16, ROT_08);
b24 = ROL64(d ^ a21, ROT_09);
d = c1 ^ ROL64(c3, 1);
b20 = ROL64(d ^ a2, ROT_10);
b11 = ROL64(d ^ a7, ROT_11);
b2 = ROL64(d ^ a12, ROT_12);
b18 = ROL64(d ^ a17, ROT_13);
b9 = ROL64(d ^ a22, ROT_14);
d = c2 ^ ROL64(c4, 1);
b5 = ROL64(d ^ a3, ROT_15);
b21 = ROL64(d ^ a8, ROT_16);
b12 = ROL64(d ^ a13, ROT_17);
b3 = ROL64(d ^ a18, ROT_18);
b19 = ROL64(d ^ a23, ROT_19);
d = c3 ^ ROL64(c0, 1);
b15 = ROL64(d ^ a4, ROT_20);
b6 = ROL64(d ^ a9, ROT_21);
b22 = ROL64(d ^ a14, ROT_22);
b13 = ROL64(d ^ a19, ROT_23);
b4 = ROL64(d ^ a24, ROT_24);
/* Chi + Iota steps */
a0 = b0 ^ (~b1 & b2) ^ roundconstants[i];
a1 = b1 ^ (~b2 & b3);
a2 = b2 ^ (~b3 & b4);
a3 = b3 ^ (~b4 & b0);
a4 = b4 ^ (~b0 & b1);
a5 = b5 ^ (~b6 & b7);
a6 = b6 ^ (~b7 & b8);
a7 = b7 ^ (~b8 & b9);
a8 = b8 ^ (~b9 & b5);
a9 = b9 ^ (~b5 & b6);
a10 = b10 ^ (~b11 & b12);
a11 = b11 ^ (~b12 & b13);
a12 = b12 ^ (~b13 & b14);
a13 = b13 ^ (~b14 & b10);
a14 = b14 ^ (~b10 & b11);
a15 = b15 ^ (~b16 & b17);
a16 = b16 ^ (~b17 & b18);
a17 = b17 ^ (~b18 & b19);
a18 = b18 ^ (~b19 & b15);
a19 = b19 ^ (~b15 & b16);
a20 = b20 ^ (~b21 & b22);
a21 = b21 ^ (~b22 & b23);
a22 = b22 ^ (~b23 & b24);
a23 = b23 ^ (~b24 & b20);
a24 = b24 ^ (~b20 & b21);
}
state[0] = a0;
state[1] = a1;
state[2] = a2;
state[3] = a3;
state[4] = a4;
state[5] = a5;
state[6] = a6;
state[7] = a7;
state[8] = a8;
state[9] = a9;
state[10] = a10;
state[11] = a11;
state[12] = a12;
state[13] = a13;
state[14] = a14;
state[15] = a15;
state[16] = a16;
state[17] = a17;
state[18] = a18;
state[19] = a19;
state[20] = a20;
state[21] = a21;
state[22] = a22;
state[23] = a23;
state[24] = a24;
}