From 331efcf4db27f9c602a78cc9451a666a981f7c4e Mon Sep 17 00:00:00 2001 From: xicilion Date: Wed, 31 Jul 2024 20:29:26 +0800 Subject: [PATCH 1/3] juice, refactor: only respond to binding request messages with USE-CANDIDATE set to 0. --- juice/src/conn_mux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/juice/src/conn_mux.c b/juice/src/conn_mux.c index ea1da9aa1..b64839a9d 100644 --- a/juice/src/conn_mux.c +++ b/juice/src/conn_mux.c @@ -297,7 +297,7 @@ static juice_agent_t *lookup_agent(conn_registry_t *registry, char *buf, size_t } } - if (registry->cb_mux_incoming) { + if (registry->cb_mux_incoming && msg.use_candidate == 0) { JLOG_DEBUG("Found STUN request with unknown ICE ufrag"); char host[ADDR_MAX_NUMERICHOST_LEN]; if (getnameinfo((const struct sockaddr *)&src->addr, src->len, host, ADDR_MAX_NUMERICHOST_LEN, NULL, 0, NI_NUMERICHOST)) { From edede25eacbd0f3435a071ea6cb8146e274bf0d3 Mon Sep 17 00:00:00 2001 From: xicilion Date: Mon, 5 Aug 2024 04:23:58 +0800 Subject: [PATCH 2/3] blst, refactor: use fips202 to refactor blst_expand_message_xof. --- blst/src/bbs_server.c | 20 +- fips202/CMakeLists.txt | 3 + fips202/include/fips202.h | 174 +++++++ fips202/src/fips202.c | 977 ++++++++++++++++++++++++++++++++++++++ libs.cmake | 1 + 5 files changed, 1166 insertions(+), 9 deletions(-) create mode 100644 fips202/CMakeLists.txt create mode 100644 fips202/include/fips202.h create mode 100644 fips202/src/fips202.c diff --git a/blst/src/bbs_server.c b/blst/src/bbs_server.c index b3091d8c1..c47ef10c1 100644 --- a/blst/src/bbs_server.c +++ b/blst/src/bbs_server.c @@ -3,7 +3,7 @@ #include "fields.h" #include "bytes.h" #include -#include +#include const POINTonE1 BLS12_381_G1_P1 = { { TO_LIMB_T(0xcbbca09048aca92e), TO_LIMB_T(0x44035f6216317fd5), @@ -26,23 +26,25 @@ const POINTonE1 BLS12_381_G1_P1_XOF = { void blst_expand_message_xof(unsigned char* bytes, size_t len_in_bytes, const unsigned char* msg, size_t msg_len, const unsigned char* DST, size_t DST_len) { - EVP_MD_CTX* ctx = EVP_MD_CTX_new(); - EVP_DigestInit_ex(ctx, EVP_shake256(), NULL); + shake256incctx ctx; - EVP_DigestUpdate(ctx, msg, msg_len); + shake256_inc_init(&ctx); + + shake256_inc_absorb(&ctx, msg, msg_len); unsigned char buf[2]; buf[0] = (len_in_bytes >> 8) & 0xff; buf[1] = len_in_bytes & 0xff; - EVP_DigestUpdate(ctx, buf, sizeof(buf)); + shake256_inc_absorb(&ctx, buf, sizeof(buf)); - EVP_DigestUpdate(ctx, DST, DST_len); + shake256_inc_absorb(&ctx, DST, DST_len); buf[0] = DST_len & 0xff; - EVP_DigestUpdate(ctx, buf, 1); + shake256_inc_absorb(&ctx, buf, 1); - EVP_DigestFinal_ex(ctx, bytes, &len_in_bytes); - EVP_MD_CTX_free(ctx); + shake256_inc_finalize(&ctx); + shake256_inc_squeeze(bytes, len_in_bytes, &ctx); + shake256_inc_ctx_release(&ctx); } void blst_hash_to_g1_xof(POINTonE1* p, const unsigned char* msg, size_t msg_len, diff --git a/fips202/CMakeLists.txt b/fips202/CMakeLists.txt new file mode 100644 index 000000000..bb1b71b7e --- /dev/null +++ b/fips202/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.6) + +include(../build_tools/cmake/Library.cmake) diff --git a/fips202/include/fips202.h b/fips202/include/fips202.h new file mode 100644 index 000000000..562bfd36b --- /dev/null +++ b/fips202/include/fips202.h @@ -0,0 +1,174 @@ +#ifndef FIPS202_H +#define FIPS202_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define SHAKE128_RATE 168 +#define SHAKE256_RATE 136 +#define SHA3_256_RATE 136 +#define SHA3_384_RATE 104 +#define SHA3_512_RATE 72 + +#define PQC_SHAKEINCCTX_BYTES (sizeof(uint64_t) * 26) +#define PQC_SHAKECTX_BYTES (sizeof(uint64_t) * 25) + +// Context for incremental API +typedef struct { + uint64_t* ctx; +} shake128incctx; + +// Context for non-incremental API +typedef struct { + uint64_t* ctx; +} shake128ctx; + +// Context for incremental API +typedef struct { + uint64_t* ctx; +} shake256incctx; + +// Context for non-incremental API +typedef struct { + uint64_t* ctx; +} shake256ctx; + +// Context for incremental API +typedef struct { + uint64_t* ctx; +} sha3_256incctx; + +// Context for incremental API +typedef struct { + uint64_t* ctx; +} sha3_384incctx; + +// Context for incremental API +typedef struct { + uint64_t* ctx; +} sha3_512incctx; + +/* Initialize the state and absorb the provided input. + * + * This function does not support being called multiple times + * with the same state. + */ +void shake128_absorb(shake128ctx* state, const uint8_t* input, size_t inlen); +/* Squeeze output out of the sponge. + * + * Supports being called multiple times + */ +void shake128_squeezeblocks(uint8_t* output, size_t nblocks, shake128ctx* state); +/* Free the state */ +void shake128_ctx_release(shake128ctx* state); +/* Copy the state. */ +void shake128_ctx_clone(shake128ctx* dest, const shake128ctx* src); + +/* Initialize incremental hashing API */ +void shake128_inc_init(shake128incctx* state); +/* Absorb more information into the XOF. + * + * Can be called multiple times. + */ +void shake128_inc_absorb(shake128incctx* state, const uint8_t* input, size_t inlen); +/* Finalize the XOF for squeezing */ +void shake128_inc_finalize(shake128incctx* state); +/* Squeeze output out of the sponge. + * + * Supports being called multiple times + */ +void shake128_inc_squeeze(uint8_t* output, size_t outlen, shake128incctx* state); +/* Copy the context of the SHAKE128 XOF */ +void shake128_inc_ctx_clone(shake128incctx* dest, const shake128incctx* src); +/* Free the context of the SHAKE128 XOF */ +void shake128_inc_ctx_release(shake128incctx* state); + +/* Initialize the state and absorb the provided input. + * + * This function does not support being called multiple times + * with the same state. + */ +void shake256_absorb(shake256ctx* state, const uint8_t* input, size_t inlen); +/* Squeeze output out of the sponge. + * + * Supports being called multiple times + */ +void shake256_squeezeblocks(uint8_t* output, size_t nblocks, shake256ctx* state); +/* Free the context held by this XOF */ +void shake256_ctx_release(shake256ctx* state); +/* Copy the context held by this XOF */ +void shake256_ctx_clone(shake256ctx* dest, const shake256ctx* src); + +/* Initialize incremental hashing API */ +void shake256_inc_init(shake256incctx* state); +void shake256_inc_absorb(shake256incctx* state, const uint8_t* input, size_t inlen); +/* Prepares for squeeze phase */ +void shake256_inc_finalize(shake256incctx* state); +/* Squeeze output out of the sponge. + * + * Supports being called multiple times + */ +void shake256_inc_squeeze(uint8_t* output, size_t outlen, shake256incctx* state); +/* Copy the state */ +void shake256_inc_ctx_clone(shake256incctx* dest, const shake256incctx* src); +/* Free the state */ +void shake256_inc_ctx_release(shake256incctx* state); + +/* One-stop SHAKE128 call */ +void shake128(uint8_t* output, size_t outlen, + const uint8_t* input, size_t inlen); + +/* One-stop SHAKE256 call */ +void shake256(uint8_t* output, size_t outlen, + const uint8_t* input, size_t inlen); + +/* Initialize the incremental hashing state */ +void sha3_256_inc_init(sha3_256incctx* state); +/* Absorb blocks into SHA3 */ +void sha3_256_inc_absorb(sha3_256incctx* state, const uint8_t* input, size_t inlen); +/* Obtain the output of the function and free `state` */ +void sha3_256_inc_finalize(uint8_t* output, sha3_256incctx* state, uint8_t p); +/* Copy the context */ +void sha3_256_inc_ctx_clone(sha3_256incctx* dest, const sha3_256incctx* src); +/* Release the state, don't use if `_finalize` has been used */ +void sha3_256_inc_ctx_release(sha3_256incctx* state); + +void sha3_256(uint8_t* output, const uint8_t* input, size_t inlen); + +/* Initialize the incremental hashing state */ +void sha3_384_inc_init(sha3_384incctx* state); +/* Absorb blocks into SHA3 */ +void sha3_384_inc_absorb(sha3_384incctx* state, const uint8_t* input, size_t inlen); +/* Obtain the output of the function and free `state` */ +void sha3_384_inc_finalize(uint8_t* output, sha3_384incctx* state, uint8_t p); +/* Copy the context */ +void sha3_384_inc_ctx_clone(sha3_384incctx* dest, const sha3_384incctx* src); +/* Release the state, don't use if `_finalize` has been used */ +void sha3_384_inc_ctx_release(sha3_384incctx* state); + +/* One-stop SHA3-384 shop */ +void sha3_384(uint8_t* output, const uint8_t* input, size_t inlen); + +/* Initialize the incremental hashing state */ +void sha3_512_inc_init(sha3_512incctx* state); +/* Absorb blocks into SHA3 */ +void sha3_512_inc_absorb(sha3_512incctx* state, const uint8_t* input, size_t inlen); +/* Obtain the output of the function and free `state` */ +void sha3_512_inc_finalize(uint8_t* output, sha3_512incctx* state, uint8_t p); +/* Copy the context */ +void sha3_512_inc_ctx_clone(sha3_512incctx* dest, const sha3_512incctx* src); +/* Release the state, don't use if `_finalize` has been used */ +void sha3_512_inc_ctx_release(sha3_512incctx* state); + +/* One-stop SHA3-512 shop */ +void sha3_512(uint8_t* output, const uint8_t* input, size_t inlen); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/fips202/src/fips202.c b/fips202/src/fips202.c new file mode 100644 index 000000000..6eb1f81e1 --- /dev/null +++ b/fips202/src/fips202.c @@ -0,0 +1,977 @@ +/* Based on the public domain implementation in + * crypto_hash/keccakc512/simple/ from http://bench.cr.yp.to/supercop.html + * by Ronny Van Keer + * and the public domain "TweetFips202" implementation + * from https://twitter.com/tweetfips202 + * by Gilles Van Assche, Daniel J. Bernstein, and Peter Schwabe */ + +#include +#include +#include +#include + +#include "fips202.h" + +#define NROUNDS 24 +#define ROL(a, offset) (((a) << (offset)) ^ ((a) >> (64 - (offset)))) + +/************************************************* + * Name: load64 + * + * Description: Load 8 bytes into uint64_t in little-endian order + * + * Arguments: - const uint8_t *x: pointer to input byte array + * + * Returns the loaded 64-bit unsigned integer + **************************************************/ +static uint64_t load64(const uint8_t* x) +{ + uint64_t r = 0; + for (size_t i = 0; i < 8; ++i) { + r |= (uint64_t)x[i] << 8 * i; + } + + return r; +} + +/************************************************* + * Name: store64 + * + * Description: Store a 64-bit integer to a byte array in little-endian order + * + * Arguments: - uint8_t *x: pointer to the output byte array + * - uint64_t u: input 64-bit unsigned integer + **************************************************/ +static void store64(uint8_t* x, uint64_t u) +{ + for (size_t i = 0; i < 8; ++i) { + x[i] = (uint8_t)(u >> 8 * i); + } +} + +/* Keccak round constants */ +static const uint64_t KeccakF_RoundConstants[NROUNDS] = { + 0x0000000000000001ULL, 0x0000000000008082ULL, + 0x800000000000808aULL, 0x8000000080008000ULL, + 0x000000000000808bULL, 0x0000000080000001ULL, + 0x8000000080008081ULL, 0x8000000000008009ULL, + 0x000000000000008aULL, 0x0000000000000088ULL, + 0x0000000080008009ULL, 0x000000008000000aULL, + 0x000000008000808bULL, 0x800000000000008bULL, + 0x8000000000008089ULL, 0x8000000000008003ULL, + 0x8000000000008002ULL, 0x8000000000000080ULL, + 0x000000000000800aULL, 0x800000008000000aULL, + 0x8000000080008081ULL, 0x8000000000008080ULL, + 0x0000000080000001ULL, 0x8000000080008008ULL +}; + +/************************************************* + * Name: KeccakF1600_StatePermute + * + * Description: The Keccak F1600 Permutation + * + * Arguments: - uint64_t *state: pointer to input/output Keccak state + **************************************************/ +static void KeccakF1600_StatePermute(uint64_t* state) +{ + int round; + + uint64_t Aba, Abe, Abi, Abo, Abu; + uint64_t Aga, Age, Agi, Ago, Agu; + uint64_t Aka, Ake, Aki, Ako, Aku; + uint64_t Ama, Ame, Ami, Amo, Amu; + uint64_t Asa, Ase, Asi, Aso, Asu; + uint64_t BCa, BCe, BCi, BCo, BCu; + uint64_t Da, De, Di, Do, Du; + uint64_t Eba, Ebe, Ebi, Ebo, Ebu; + uint64_t Ega, Ege, Egi, Ego, Egu; + uint64_t Eka, Eke, Eki, Eko, Eku; + uint64_t Ema, Eme, Emi, Emo, Emu; + uint64_t Esa, Ese, Esi, Eso, Esu; + + // copyFromState(A, state) + Aba = state[0]; + Abe = state[1]; + Abi = state[2]; + Abo = state[3]; + Abu = state[4]; + Aga = state[5]; + Age = state[6]; + Agi = state[7]; + Ago = state[8]; + Agu = state[9]; + Aka = state[10]; + Ake = state[11]; + Aki = state[12]; + Ako = state[13]; + Aku = state[14]; + Ama = state[15]; + Ame = state[16]; + Ami = state[17]; + Amo = state[18]; + Amu = state[19]; + Asa = state[20]; + Ase = state[21]; + Asi = state[22]; + Aso = state[23]; + Asu = state[24]; + + for (round = 0; round < NROUNDS; round += 2) { + // prepareTheta + BCa = Aba ^ Aga ^ Aka ^ Ama ^ Asa; + BCe = Abe ^ Age ^ Ake ^ Ame ^ Ase; + BCi = Abi ^ Agi ^ Aki ^ Ami ^ Asi; + BCo = Abo ^ Ago ^ Ako ^ Amo ^ Aso; + BCu = Abu ^ Agu ^ Aku ^ Amu ^ Asu; + + // thetaRhoPiChiIotaPrepareTheta(round , A, E) + Da = BCu ^ ROL(BCe, 1); + De = BCa ^ ROL(BCi, 1); + Di = BCe ^ ROL(BCo, 1); + Do = BCi ^ ROL(BCu, 1); + Du = BCo ^ ROL(BCa, 1); + + Aba ^= Da; + BCa = Aba; + Age ^= De; + BCe = ROL(Age, 44); + Aki ^= Di; + BCi = ROL(Aki, 43); + Amo ^= Do; + BCo = ROL(Amo, 21); + Asu ^= Du; + BCu = ROL(Asu, 14); + Eba = BCa ^ ((~BCe) & BCi); + Eba ^= KeccakF_RoundConstants[round]; + Ebe = BCe ^ ((~BCi) & BCo); + Ebi = BCi ^ ((~BCo) & BCu); + Ebo = BCo ^ ((~BCu) & BCa); + Ebu = BCu ^ ((~BCa) & BCe); + + Abo ^= Do; + BCa = ROL(Abo, 28); + Agu ^= Du; + BCe = ROL(Agu, 20); + Aka ^= Da; + BCi = ROL(Aka, 3); + Ame ^= De; + BCo = ROL(Ame, 45); + Asi ^= Di; + BCu = ROL(Asi, 61); + Ega = BCa ^ ((~BCe) & BCi); + Ege = BCe ^ ((~BCi) & BCo); + Egi = BCi ^ ((~BCo) & BCu); + Ego = BCo ^ ((~BCu) & BCa); + Egu = BCu ^ ((~BCa) & BCe); + + Abe ^= De; + BCa = ROL(Abe, 1); + Agi ^= Di; + BCe = ROL(Agi, 6); + Ako ^= Do; + BCi = ROL(Ako, 25); + Amu ^= Du; + BCo = ROL(Amu, 8); + Asa ^= Da; + BCu = ROL(Asa, 18); + Eka = BCa ^ ((~BCe) & BCi); + Eke = BCe ^ ((~BCi) & BCo); + Eki = BCi ^ ((~BCo) & BCu); + Eko = BCo ^ ((~BCu) & BCa); + Eku = BCu ^ ((~BCa) & BCe); + + Abu ^= Du; + BCa = ROL(Abu, 27); + Aga ^= Da; + BCe = ROL(Aga, 36); + Ake ^= De; + BCi = ROL(Ake, 10); + Ami ^= Di; + BCo = ROL(Ami, 15); + Aso ^= Do; + BCu = ROL(Aso, 56); + Ema = BCa ^ ((~BCe) & BCi); + Eme = BCe ^ ((~BCi) & BCo); + Emi = BCi ^ ((~BCo) & BCu); + Emo = BCo ^ ((~BCu) & BCa); + Emu = BCu ^ ((~BCa) & BCe); + + Abi ^= Di; + BCa = ROL(Abi, 62); + Ago ^= Do; + BCe = ROL(Ago, 55); + Aku ^= Du; + BCi = ROL(Aku, 39); + Ama ^= Da; + BCo = ROL(Ama, 41); + Ase ^= De; + BCu = ROL(Ase, 2); + Esa = BCa ^ ((~BCe) & BCi); + Ese = BCe ^ ((~BCi) & BCo); + Esi = BCi ^ ((~BCo) & BCu); + Eso = BCo ^ ((~BCu) & BCa); + Esu = BCu ^ ((~BCa) & BCe); + + // prepareTheta + BCa = Eba ^ Ega ^ Eka ^ Ema ^ Esa; + BCe = Ebe ^ Ege ^ Eke ^ Eme ^ Ese; + BCi = Ebi ^ Egi ^ Eki ^ Emi ^ Esi; + BCo = Ebo ^ Ego ^ Eko ^ Emo ^ Eso; + BCu = Ebu ^ Egu ^ Eku ^ Emu ^ Esu; + + // thetaRhoPiChiIotaPrepareTheta(round+1, E, A) + Da = BCu ^ ROL(BCe, 1); + De = BCa ^ ROL(BCi, 1); + Di = BCe ^ ROL(BCo, 1); + Do = BCi ^ ROL(BCu, 1); + Du = BCo ^ ROL(BCa, 1); + + Eba ^= Da; + BCa = Eba; + Ege ^= De; + BCe = ROL(Ege, 44); + Eki ^= Di; + BCi = ROL(Eki, 43); + Emo ^= Do; + BCo = ROL(Emo, 21); + Esu ^= Du; + BCu = ROL(Esu, 14); + Aba = BCa ^ ((~BCe) & BCi); + Aba ^= KeccakF_RoundConstants[round + 1]; + Abe = BCe ^ ((~BCi) & BCo); + Abi = BCi ^ ((~BCo) & BCu); + Abo = BCo ^ ((~BCu) & BCa); + Abu = BCu ^ ((~BCa) & BCe); + + Ebo ^= Do; + BCa = ROL(Ebo, 28); + Egu ^= Du; + BCe = ROL(Egu, 20); + Eka ^= Da; + BCi = ROL(Eka, 3); + Eme ^= De; + BCo = ROL(Eme, 45); + Esi ^= Di; + BCu = ROL(Esi, 61); + Aga = BCa ^ ((~BCe) & BCi); + Age = BCe ^ ((~BCi) & BCo); + Agi = BCi ^ ((~BCo) & BCu); + Ago = BCo ^ ((~BCu) & BCa); + Agu = BCu ^ ((~BCa) & BCe); + + Ebe ^= De; + BCa = ROL(Ebe, 1); + Egi ^= Di; + BCe = ROL(Egi, 6); + Eko ^= Do; + BCi = ROL(Eko, 25); + Emu ^= Du; + BCo = ROL(Emu, 8); + Esa ^= Da; + BCu = ROL(Esa, 18); + Aka = BCa ^ ((~BCe) & BCi); + Ake = BCe ^ ((~BCi) & BCo); + Aki = BCi ^ ((~BCo) & BCu); + Ako = BCo ^ ((~BCu) & BCa); + Aku = BCu ^ ((~BCa) & BCe); + + Ebu ^= Du; + BCa = ROL(Ebu, 27); + Ega ^= Da; + BCe = ROL(Ega, 36); + Eke ^= De; + BCi = ROL(Eke, 10); + Emi ^= Di; + BCo = ROL(Emi, 15); + Eso ^= Do; + BCu = ROL(Eso, 56); + Ama = BCa ^ ((~BCe) & BCi); + Ame = BCe ^ ((~BCi) & BCo); + Ami = BCi ^ ((~BCo) & BCu); + Amo = BCo ^ ((~BCu) & BCa); + Amu = BCu ^ ((~BCa) & BCe); + + Ebi ^= Di; + BCa = ROL(Ebi, 62); + Ego ^= Do; + BCe = ROL(Ego, 55); + Eku ^= Du; + BCi = ROL(Eku, 39); + Ema ^= Da; + BCo = ROL(Ema, 41); + Ese ^= De; + BCu = ROL(Ese, 2); + Asa = BCa ^ ((~BCe) & BCi); + Ase = BCe ^ ((~BCi) & BCo); + Asi = BCi ^ ((~BCo) & BCu); + Aso = BCo ^ ((~BCu) & BCa); + Asu = BCu ^ ((~BCa) & BCe); + } + + // copyToState(state, A) + state[0] = Aba; + state[1] = Abe; + state[2] = Abi; + state[3] = Abo; + state[4] = Abu; + state[5] = Aga; + state[6] = Age; + state[7] = Agi; + state[8] = Ago; + state[9] = Agu; + state[10] = Aka; + state[11] = Ake; + state[12] = Aki; + state[13] = Ako; + state[14] = Aku; + state[15] = Ama; + state[16] = Ame; + state[17] = Ami; + state[18] = Amo; + state[19] = Amu; + state[20] = Asa; + state[21] = Ase; + state[22] = Asi; + state[23] = Aso; + state[24] = Asu; +} + +/************************************************* + * Name: keccak_absorb + * + * Description: Absorb step of Keccak; + * non-incremental, starts by zeroeing the state. + * + * Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state + * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) + * - const uint8_t *m: pointer to input to be absorbed into s + * - size_t mlen: length of input in bytes + * - uint8_t p: domain-separation byte for different + * Keccak-derived functions + **************************************************/ +static void keccak_absorb(uint64_t* s, uint32_t r, const uint8_t* m, + size_t mlen, uint8_t p) +{ + size_t i; + uint8_t t[200]; + + /* Zero state */ + for (i = 0; i < 25; ++i) { + s[i] = 0; + } + + while (mlen >= r) { + for (i = 0; i < r / 8; ++i) { + s[i] ^= load64(m + 8 * i); + } + + KeccakF1600_StatePermute(s); + mlen -= r; + m += r; + } + + for (i = 0; i < r; ++i) { + t[i] = 0; + } + for (i = 0; i < mlen; ++i) { + t[i] = m[i]; + } + t[i] = p; + t[r - 1] |= 128; + for (i = 0; i < r / 8; ++i) { + s[i] ^= load64(t + 8 * i); + } +} + +/************************************************* + * Name: keccak_squeezeblocks + * + * Description: Squeeze step of Keccak. Squeezes full blocks of r bytes each. + * Modifies the state. Can be called multiple times to keep + * squeezing, i.e., is incremental. + * + * Arguments: - uint8_t *h: pointer to output blocks + * - size_t nblocks: number of blocks to be + * squeezed (written to h) + * - uint64_t *s: pointer to input/output Keccak state + * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) + **************************************************/ +static void keccak_squeezeblocks(uint8_t* h, size_t nblocks, + uint64_t* s, uint32_t r) +{ + while (nblocks > 0) { + KeccakF1600_StatePermute(s); + for (size_t i = 0; i < (r >> 3); i++) { + store64(h + 8 * i, s[i]); + } + h += r; + nblocks--; + } +} + +/************************************************* + * Name: keccak_inc_init + * + * Description: Initializes the incremental Keccak state to zero. + * + * Arguments: - uint64_t *s_inc: pointer to input/output incremental state + * First 25 values represent Keccak state. + * 26th value represents either the number of absorbed bytes + * that have not been permuted, or not-yet-squeezed bytes. + **************************************************/ +static void keccak_inc_init(uint64_t* s_inc) +{ + size_t i; + + for (i = 0; i < 25; ++i) { + s_inc[i] = 0; + } + s_inc[25] = 0; +} + +/************************************************* + * Name: keccak_inc_absorb + * + * Description: Incremental keccak absorb + * Preceded by keccak_inc_init, succeeded by keccak_inc_finalize + * + * Arguments: - uint64_t *s_inc: pointer to input/output incremental state + * First 25 values represent Keccak state. + * 26th value represents either the number of absorbed bytes + * that have not been permuted, or not-yet-squeezed bytes. + * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) + * - const uint8_t *m: pointer to input to be absorbed into s + * - size_t mlen: length of input in bytes + **************************************************/ +static void keccak_inc_absorb(uint64_t* s_inc, uint32_t r, const uint8_t* m, + size_t mlen) +{ + size_t i; + + /* Recall that s_inc[25] is the non-absorbed bytes xored into the state */ + while (mlen + s_inc[25] >= r) { + for (i = 0; i < r - (uint32_t)s_inc[25]; i++) { + /* Take the i'th byte from message + xor with the s_inc[25] + i'th byte of the state; little-endian */ + s_inc[(s_inc[25] + i) >> 3] ^= (uint64_t)m[i] << (8 * ((s_inc[25] + i) & 0x07)); + } + mlen -= (size_t)(r - s_inc[25]); + m += r - s_inc[25]; + s_inc[25] = 0; + + KeccakF1600_StatePermute(s_inc); + } + + for (i = 0; i < mlen; i++) { + s_inc[(s_inc[25] + i) >> 3] ^= (uint64_t)m[i] << (8 * ((s_inc[25] + i) & 0x07)); + } + s_inc[25] += mlen; +} + +/************************************************* + * Name: keccak_inc_finalize + * + * Description: Finalizes Keccak absorb phase, prepares for squeezing + * + * Arguments: - uint64_t *s_inc: pointer to input/output incremental state + * First 25 values represent Keccak state. + * 26th value represents either the number of absorbed bytes + * that have not been permuted, or not-yet-squeezed bytes. + * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) + * - uint8_t p: domain-separation byte for different + * Keccak-derived functions + **************************************************/ +static void keccak_inc_finalize(uint64_t* s_inc, uint32_t r, uint8_t p) +{ + /* After keccak_inc_absorb, we are guaranteed that s_inc[25] < r, + so we can always use one more byte for p in the current state. */ + s_inc[s_inc[25] >> 3] ^= (uint64_t)p << (8 * (s_inc[25] & 0x07)); + s_inc[(r - 1) >> 3] ^= (uint64_t)128 << (8 * ((r - 1) & 0x07)); + s_inc[25] = 0; +} + +/************************************************* + * Name: keccak_inc_squeeze + * + * Description: Incremental Keccak squeeze; can be called on byte-level + * + * Arguments: - uint8_t *h: pointer to output bytes + * - size_t outlen: number of bytes to be squeezed + * - uint64_t *s_inc: pointer to input/output incremental state + * First 25 values represent Keccak state. + * 26th value represents either the number of absorbed bytes + * that have not been permuted, or not-yet-squeezed bytes. + * - uint32_t r: rate in bytes (e.g., 168 for SHAKE128) + **************************************************/ +static void keccak_inc_squeeze(uint8_t* h, size_t outlen, + uint64_t* s_inc, uint32_t r) +{ + size_t i; + + /* First consume any bytes we still have sitting around */ + for (i = 0; i < outlen && i < s_inc[25]; i++) { + /* There are s_inc[25] bytes left, so r - s_inc[25] is the first + available byte. We consume from there, i.e., up to r. */ + h[i] = (uint8_t)(s_inc[(r - s_inc[25] + i) >> 3] >> (8 * ((r - s_inc[25] + i) & 0x07))); + } + h += i; + outlen -= i; + s_inc[25] -= i; + + /* Then squeeze the remaining necessary blocks */ + while (outlen > 0) { + KeccakF1600_StatePermute(s_inc); + + for (i = 0; i < outlen && i < r; i++) { + h[i] = (uint8_t)(s_inc[i >> 3] >> (8 * (i & 0x07))); + } + h += i; + outlen -= i; + s_inc[25] = r - i; + } +} + +void shake128_inc_init(shake128incctx* state) +{ + state->ctx = (uint64_t *)malloc(PQC_SHAKEINCCTX_BYTES); + if (state->ctx == NULL) { + exit(111); + } + keccak_inc_init(state->ctx); +} + +void shake128_inc_absorb(shake128incctx* state, const uint8_t* input, size_t inlen) +{ + keccak_inc_absorb(state->ctx, SHAKE128_RATE, input, inlen); +} + +void shake128_inc_finalize(shake128incctx* state) +{ + keccak_inc_finalize(state->ctx, SHAKE128_RATE, 0x1F); +} + +void shake128_inc_squeeze(uint8_t* output, size_t outlen, shake128incctx* state) +{ + keccak_inc_squeeze(output, outlen, state->ctx, SHAKE128_RATE); +} + +void shake128_inc_ctx_clone(shake128incctx* dest, const shake128incctx* src) +{ + dest->ctx = (uint64_t *)malloc(PQC_SHAKEINCCTX_BYTES); + if (dest->ctx == NULL) { + exit(111); + } + memcpy(dest->ctx, src->ctx, PQC_SHAKEINCCTX_BYTES); +} + +void shake128_inc_ctx_release(shake128incctx* state) +{ + free(state->ctx); +} + +void shake256_inc_init(shake256incctx* state) +{ + state->ctx = (uint64_t *)malloc(PQC_SHAKEINCCTX_BYTES); + if (state->ctx == NULL) { + exit(111); + } + keccak_inc_init(state->ctx); +} + +void shake256_inc_absorb(shake256incctx* state, const uint8_t* input, size_t inlen) +{ + keccak_inc_absorb(state->ctx, SHAKE256_RATE, input, inlen); +} + +void shake256_inc_finalize(shake256incctx* state) +{ + keccak_inc_finalize(state->ctx, SHAKE256_RATE, 0x1F); +} + +void shake256_inc_squeeze(uint8_t* output, size_t outlen, shake256incctx* state) +{ + keccak_inc_squeeze(output, outlen, state->ctx, SHAKE256_RATE); +} + +void shake256_inc_ctx_clone(shake256incctx* dest, const shake256incctx* src) +{ + dest->ctx = (uint64_t *)malloc(PQC_SHAKEINCCTX_BYTES); + if (dest->ctx == NULL) { + exit(111); + } + memcpy(dest->ctx, src->ctx, PQC_SHAKEINCCTX_BYTES); +} + +void shake256_inc_ctx_release(shake256incctx* state) +{ + free(state->ctx); +} + +/************************************************* + * Name: shake128_absorb + * + * Description: Absorb step of the SHAKE128 XOF. + * non-incremental, starts by zeroeing the state. + * + * Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state + * - const uint8_t *input: pointer to input to be absorbed + * into s + * - size_t inlen: length of input in bytes + **************************************************/ +void shake128_absorb(shake128ctx* state, const uint8_t* input, size_t inlen) +{ + state->ctx = (uint64_t *)malloc(PQC_SHAKECTX_BYTES); + if (state->ctx == NULL) { + exit(111); + } + keccak_absorb(state->ctx, SHAKE128_RATE, input, inlen, 0x1F); +} + +/************************************************* + * Name: shake128_squeezeblocks + * + * Description: Squeeze step of SHAKE128 XOF. Squeezes full blocks of + * SHAKE128_RATE bytes each. Modifies the state. Can be called + * multiple times to keep squeezing, i.e., is incremental. + * + * Arguments: - uint8_t *output: pointer to output blocks + * - size_t nblocks: number of blocks to be squeezed + * (written to output) + * - shake128ctx *state: pointer to input/output Keccak state + **************************************************/ +void shake128_squeezeblocks(uint8_t* output, size_t nblocks, shake128ctx* state) +{ + keccak_squeezeblocks(output, nblocks, state->ctx, SHAKE128_RATE); +} + +void shake128_ctx_clone(shake128ctx* dest, const shake128ctx* src) +{ + dest->ctx = (uint64_t *)malloc(PQC_SHAKECTX_BYTES); + if (dest->ctx == NULL) { + exit(111); + } + memcpy(dest->ctx, src->ctx, PQC_SHAKECTX_BYTES); +} + +/** Release the allocated state. Call only once. */ +void shake128_ctx_release(shake128ctx* state) +{ + free(state->ctx); +} + +/************************************************* + * Name: shake256_absorb + * + * Description: Absorb step of the SHAKE256 XOF. + * non-incremental, starts by zeroeing the state. + * + * Arguments: - shake256ctx *state: pointer to (uninitialized) output Keccak state + * - const uint8_t *input: pointer to input to be absorbed + * into s + * - size_t inlen: length of input in bytes + **************************************************/ +void shake256_absorb(shake256ctx* state, const uint8_t* input, size_t inlen) +{ + state->ctx = (uint64_t *)malloc(PQC_SHAKECTX_BYTES); + if (state->ctx == NULL) { + exit(111); + } + keccak_absorb(state->ctx, SHAKE256_RATE, input, inlen, 0x1F); +} + +/************************************************* + * Name: shake256_squeezeblocks + * + * Description: Squeeze step of SHAKE256 XOF. Squeezes full blocks of + * SHAKE256_RATE bytes each. Modifies the state. Can be called + * multiple times to keep squeezing, i.e., is incremental. + * + * Arguments: - uint8_t *output: pointer to output blocks + * - size_t nblocks: number of blocks to be squeezed + * (written to output) + * - shake256ctx *state: pointer to input/output Keccak state + **************************************************/ +void shake256_squeezeblocks(uint8_t* output, size_t nblocks, shake256ctx* state) +{ + keccak_squeezeblocks(output, nblocks, state->ctx, SHAKE256_RATE); +} + +void shake256_ctx_clone(shake256ctx* dest, const shake256ctx* src) +{ + dest->ctx = (uint64_t *)malloc(PQC_SHAKECTX_BYTES); + if (dest->ctx == NULL) { + exit(111); + } + memcpy(dest->ctx, src->ctx, PQC_SHAKECTX_BYTES); +} + +/** Release the allocated state. Call only once. */ +void shake256_ctx_release(shake256ctx* state) +{ + free(state->ctx); +} + +/************************************************* + * Name: shake128 + * + * Description: SHAKE128 XOF with non-incremental API + * + * Arguments: - uint8_t *output: pointer to output + * - size_t outlen: requested output length in bytes + * - const uint8_t *input: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void shake128(uint8_t* output, size_t outlen, + const uint8_t* input, size_t inlen) +{ + size_t nblocks = outlen / SHAKE128_RATE; + uint8_t t[SHAKE128_RATE]; + shake128ctx s; + + shake128_absorb(&s, input, inlen); + shake128_squeezeblocks(output, nblocks, &s); + + output += nblocks * SHAKE128_RATE; + outlen -= nblocks * SHAKE128_RATE; + + if (outlen) { + shake128_squeezeblocks(t, 1, &s); + for (size_t i = 0; i < outlen; ++i) { + output[i] = t[i]; + } + } + shake128_ctx_release(&s); +} + +/************************************************* + * Name: shake256 + * + * Description: SHAKE256 XOF with non-incremental API + * + * Arguments: - uint8_t *output: pointer to output + * - size_t outlen: requested output length in bytes + * - const uint8_t *input: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void shake256(uint8_t* output, size_t outlen, + const uint8_t* input, size_t inlen) +{ + size_t nblocks = outlen / SHAKE256_RATE; + uint8_t t[SHAKE256_RATE]; + shake256ctx s; + + shake256_absorb(&s, input, inlen); + shake256_squeezeblocks(output, nblocks, &s); + + output += nblocks * SHAKE256_RATE; + outlen -= nblocks * SHAKE256_RATE; + + if (outlen) { + shake256_squeezeblocks(t, 1, &s); + for (size_t i = 0; i < outlen; ++i) { + output[i] = t[i]; + } + } + shake256_ctx_release(&s); +} + +void sha3_256_inc_init(sha3_256incctx* state) +{ + state->ctx = (uint64_t *)malloc(PQC_SHAKEINCCTX_BYTES); + if (state->ctx == NULL) { + exit(111); + } + keccak_inc_init(state->ctx); +} + +void sha3_256_inc_ctx_clone(sha3_256incctx* dest, const sha3_256incctx* src) +{ + dest->ctx = (uint64_t *)malloc(PQC_SHAKEINCCTX_BYTES); + if (dest->ctx == NULL) { + exit(111); + } + memcpy(dest->ctx, src->ctx, PQC_SHAKEINCCTX_BYTES); +} + +void sha3_256_inc_ctx_release(sha3_256incctx* state) +{ + free(state->ctx); +} + +void sha3_256_inc_absorb(sha3_256incctx* state, const uint8_t* input, size_t inlen) +{ + keccak_inc_absorb(state->ctx, SHA3_256_RATE, input, inlen); +} + +void sha3_256_inc_finalize(uint8_t* output, sha3_256incctx* state, uint8_t p) +{ + uint8_t t[SHA3_256_RATE]; + keccak_inc_finalize(state->ctx, SHA3_256_RATE, p); + + keccak_squeezeblocks(t, 1, state->ctx, SHA3_256_RATE); + + sha3_256_inc_ctx_release(state); + + for (size_t i = 0; i < 32; i++) { + output[i] = t[i]; + } +} + +/************************************************* + * Name: sha3_256 + * + * Description: SHA3-256 with non-incremental API + * + * Arguments: - uint8_t *output: pointer to output + * - const uint8_t *input: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void sha3_256(uint8_t* output, const uint8_t* input, size_t inlen) +{ + uint64_t s[25]; + uint8_t t[SHA3_256_RATE]; + + /* Absorb input */ + keccak_absorb(s, SHA3_256_RATE, input, inlen, 0x06); + + /* Squeeze output */ + keccak_squeezeblocks(t, 1, s, SHA3_256_RATE); + + for (size_t i = 0; i < 32; i++) { + output[i] = t[i]; + } +} + +void sha3_384_inc_init(sha3_384incctx* state) +{ + state->ctx = (uint64_t *)malloc(PQC_SHAKEINCCTX_BYTES); + if (state->ctx == NULL) { + exit(111); + } + keccak_inc_init(state->ctx); +} + +void sha3_384_inc_ctx_clone(sha3_384incctx* dest, const sha3_384incctx* src) +{ + dest->ctx = (uint64_t *)malloc(PQC_SHAKEINCCTX_BYTES); + if (dest->ctx == NULL) { + exit(111); + } + memcpy(dest->ctx, src->ctx, PQC_SHAKEINCCTX_BYTES); +} + +void sha3_384_inc_absorb(sha3_384incctx* state, const uint8_t* input, size_t inlen) +{ + keccak_inc_absorb(state->ctx, SHA3_384_RATE, input, inlen); +} + +void sha3_384_inc_ctx_release(sha3_384incctx* state) +{ + free(state->ctx); +} + +void sha3_384_inc_finalize(uint8_t* output, sha3_384incctx* state, uint8_t p) +{ + uint8_t t[SHA3_384_RATE]; + keccak_inc_finalize(state->ctx, SHA3_384_RATE, p); + + keccak_squeezeblocks(t, 1, state->ctx, SHA3_384_RATE); + + sha3_384_inc_ctx_release(state); + + for (size_t i = 0; i < 48; i++) { + output[i] = t[i]; + } +} + +/************************************************* + * Name: sha3_384 + * + * Description: SHA3-256 with non-incremental API + * + * Arguments: - uint8_t *output: pointer to output + * - const uint8_t *input: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void sha3_384(uint8_t* output, const uint8_t* input, size_t inlen) +{ + uint64_t s[25]; + uint8_t t[SHA3_384_RATE]; + + /* Absorb input */ + keccak_absorb(s, SHA3_384_RATE, input, inlen, 0x06); + + /* Squeeze output */ + keccak_squeezeblocks(t, 1, s, SHA3_384_RATE); + + for (size_t i = 0; i < 48; i++) { + output[i] = t[i]; + } +} + +void sha3_512_inc_init(sha3_512incctx* state) +{ + state->ctx = (uint64_t *)malloc(PQC_SHAKEINCCTX_BYTES); + if (state->ctx == NULL) { + exit(111); + } + keccak_inc_init(state->ctx); +} + +void sha3_512_inc_ctx_clone(sha3_512incctx* dest, const sha3_512incctx* src) +{ + dest->ctx = (uint64_t *)malloc(PQC_SHAKEINCCTX_BYTES); + if (dest->ctx == NULL) { + exit(111); + } + memcpy(dest->ctx, src->ctx, PQC_SHAKEINCCTX_BYTES); +} + +void sha3_512_inc_absorb(sha3_512incctx* state, const uint8_t* input, size_t inlen) +{ + keccak_inc_absorb(state->ctx, SHA3_512_RATE, input, inlen); +} + +void sha3_512_inc_ctx_release(sha3_512incctx* state) +{ + free(state->ctx); +} + +void sha3_512_inc_finalize(uint8_t* output, sha3_512incctx* state, uint8_t p) +{ + uint8_t t[SHA3_512_RATE]; + keccak_inc_finalize(state->ctx, SHA3_512_RATE, p); + + keccak_squeezeblocks(t, 1, state->ctx, SHA3_512_RATE); + + sha3_512_inc_ctx_release(state); + + for (size_t i = 0; i < 64; i++) { + output[i] = t[i]; + } +} + +/************************************************* + * Name: sha3_512 + * + * Description: SHA3-512 with non-incremental API + * + * Arguments: - uint8_t *output: pointer to output + * - const uint8_t *input: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void sha3_512(uint8_t* output, const uint8_t* input, size_t inlen) +{ + uint64_t s[25]; + uint8_t t[SHA3_512_RATE]; + + /* Absorb input */ + keccak_absorb(s, SHA3_512_RATE, input, inlen, 0x06); + + /* Squeeze output */ + keccak_squeezeblocks(t, 1, s, SHA3_512_RATE); + + for (size_t i = 0; i < 64; i++) { + output[i] = t[i]; + } +} diff --git a/libs.cmake b/libs.cmake index 48c285217..36e257623 100644 --- a/libs.cmake +++ b/libs.cmake @@ -20,6 +20,7 @@ set(libs juice usrsctp openssl + fips202 blst jssdk unzip From a34992c7cc7e1f16b77b362659d58aff1a0daad7 Mon Sep 17 00:00:00 2001 From: xicilion Date: Mon, 5 Aug 2024 07:51:49 +0000 Subject: [PATCH 3/3] build, refactor: reorder the order of links and fix the link errors in Linux. --- libs.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs.cmake b/libs.cmake index 36e257623..fc8608beb 100644 --- a/libs.cmake +++ b/libs.cmake @@ -20,8 +20,8 @@ set(libs juice usrsctp openssl - fips202 blst + fips202 jssdk unzip uv