#include "shares.h" #include #include #include "endian.h" #include "forceinline.h" #include "interleave.h" forceinline uint32_t ROR32(uint32_t x, int n) { return x >> n | x << (-n & 31); } forceinline uint64_t ROR64(uint64_t x, int n) { return x >> n | x << (-n & 63); } void generate_shares(uint32_t* s, int num_shares, const uint8_t* data, uint64_t len); void combine_shares(uint8_t* data, uint64_t len, const uint32_t* s, int num_shares); void generate_shares_encrypt(const unsigned char* m, mask_m_uint32_t* ms, const unsigned long long mlen, const unsigned char* ad, mask_ad_uint32_t* ads, const unsigned long long adlen, const unsigned char* npub, mask_npub_uint32_t* npubs, const unsigned char* k, mask_key_uint32_t* ks) { generate_shares((uint32_t*)ks, NUM_SHARES_KEY, k, CRYPTO_KEYBYTES); generate_shares((uint32_t*)npubs, NUM_SHARES_NPUB, npub, CRYPTO_NPUBBYTES); generate_shares((uint32_t*)ads, NUM_SHARES_AD, ad, adlen); generate_shares((uint32_t*)ms, NUM_SHARES_M, m, mlen); } void generate_shares_decrypt(const unsigned char* c, mask_c_uint32_t* cs, const unsigned long long clen, const unsigned char* ad, mask_ad_uint32_t* ads, const unsigned long long adlen, const unsigned char* npub, mask_npub_uint32_t* npubs, const unsigned char* k, mask_key_uint32_t* ks) { unsigned long long mlen = clen - CRYPTO_ABYTES; mask_c_uint32_t* ts = cs + NUM_WORDS(mlen); generate_shares((uint32_t*)ks, NUM_SHARES_KEY, k, CRYPTO_KEYBYTES); generate_shares((uint32_t*)npubs, NUM_SHARES_NPUB, npub, CRYPTO_NPUBBYTES); generate_shares((uint32_t*)ads, NUM_SHARES_AD, ad, adlen); generate_shares((uint32_t*)cs, NUM_SHARES_C, c, mlen); generate_shares((uint32_t*)ts, NUM_SHARES_C, c + mlen, CRYPTO_ABYTES); } void combine_shares_encrypt(const mask_c_uint32_t* cs, unsigned char* c, unsigned long long clen) { unsigned long long mlen = clen - CRYPTO_ABYTES; const mask_c_uint32_t* ts = cs + NUM_WORDS(mlen); combine_shares(c, mlen, (uint32_t*)cs, NUM_SHARES_C); combine_shares(c + mlen, CRYPTO_ABYTES, (uint32_t*)ts, NUM_SHARES_C); } void combine_shares_decrypt(const mask_m_uint32_t* ms, unsigned char* m, unsigned long long mlen) { combine_shares(m, mlen, (uint32_t*)ms, NUM_SHARES_M); } void generate_shares(uint32_t* s, int num_shares, const uint8_t* data, uint64_t len) { uint32_t rnd0, rnd1; uint64_t rnd, i; /* generate random shares */ for (i = 0; i < NUM_WORDS(len); i += 2) { s[(i + 0) * num_shares + 0] = 0; s[(i + 1) * num_shares + 0] = 0; for (int d = 1; d < num_shares; ++d) { RND(rnd0); RND(rnd1); s[(i + 0) * num_shares + d] = rnd0; s[(i + 1) * num_shares + d] = rnd1; #if ASCON_EXTERN_BI s[(i + 0) * num_shares + 0] ^= ROR32(rnd0, ROT(d)); s[(i + 1) * num_shares + 0] ^= ROR32(rnd1, ROT(d)); #else rnd = ROR64((uint64_t)rnd1 << 32 | rnd0, ROT(2 * d)); s[(i + 0) * num_shares + 0] ^= (uint32_t)rnd; s[(i + 1) * num_shares + 0] ^= (uint32_t)(rnd >> 32); #endif } } /* mask complete words */ for (i = 0; i < len / 8; ++i) { uint64_t x; memcpy(&x, data + i * 8, 8); x = U64BIG(x); #if ASCON_EXTERN_BI x = TOBI(x); #endif s[(2 * i + 0) * num_shares + 0] ^= (uint32_t)x; s[(2 * i + 1) * num_shares + 0] ^= (uint32_t)(x >> 32); } /* mask remaining bytes */ if ((len / 8 * 8) != len) { uint64_t x = 0; for (i = (len / 8) * 8; i < len; ++i) { x ^= (uint64_t)data[i] << ((i % 8) * 8); } x = U64BIG(x); #if ASCON_EXTERN_BI x = TOBI(x); #endif s[(2 * (len / 8) + 0) * num_shares + 0] ^= (uint32_t)x; s[(2 * (len / 8) + 1) * num_shares + 0] ^= (uint32_t)(x >> 32); } } void combine_shares(uint8_t* data, uint64_t len, const uint32_t* s, int num_shares) { uint32_t rnd0, rnd1; uint64_t i; /* unmask complete words */ for (i = 0; i < len / 8; ++i) { uint64_t x = 0; for (int d = 0; d < num_shares; ++d) { rnd0 = s[(2 * i + 0) * num_shares + d]; rnd1 = s[(2 * i + 1) * num_shares + d]; #if ASCON_EXTERN_BI x ^= (uint64_t)ROR32(rnd0, ROT(d)); x ^= (uint64_t)ROR32(rnd1, ROT(d)) << 32; #else x ^= ROR64((uint64_t)rnd1 << 32 | rnd0, ROT(2 * d)); #endif } #if ASCON_EXTERN_BI x = FROMBI(x); #endif x = U64BIG(x); memcpy(data + i * 8, &x, 8); } /* unmask remaining bytes */ if ((len / 8 * 8) != len) { uint64_t x = 0; for (int d = 0; d < num_shares; ++d) { rnd0 = s[(2 * (len / 8) + 0) * num_shares + d]; rnd1 = s[(2 * (len / 8) + 1) * num_shares + d]; #if ASCON_EXTERN_BI x ^= (uint64_t)ROR32(rnd0, ROT(d)); x ^= (uint64_t)ROR32(rnd1, ROT(d)) << 32; #else x ^= ROR64((uint64_t)rnd1 << 32 | rnd0, ROT(2 * d)); #endif } #if ASCON_EXTERN_BI x = FROMBI(x); #endif x = U64BIG(x); for (i = (len / 8) * 8; i < len; ++i) { data[i] = x >> ((i % 8) * 8); } } }