From 0bc743867b4c40c4cb8667531434897d0880ea83 Mon Sep 17 00:00:00 2001 From: Alexandre Adomnicai Date: Thu, 5 Mar 2020 00:26:13 +0000 Subject: [PATCH] giftcofb128v1.opt32 --- gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/api.h | 5 +++++ gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/cofb.h | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/encrypt.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/endian.h | 14 ++++++++++++++ gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/giftb128.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/giftb128.h | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/key_schedule.h | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 498 insertions(+) create mode 100644 gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/api.h create mode 100644 gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/cofb.h create mode 100644 gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/encrypt.c create mode 100644 gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/endian.h create mode 100644 gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/giftb128.c create mode 100644 gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/giftb128.h create mode 100644 gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/key_schedule.h diff --git a/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/api.h b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/api.h new file mode 100644 index 0000000..fb1d58b --- /dev/null +++ b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/api.h @@ -0,0 +1,5 @@ +#define CRYPTO_KEYBYTES 16 +#define CRYPTO_NSECBYTES 0 +#define CRYPTO_NPUBBYTES 16 +#define CRYPTO_ABYTES 16 +#define CRYPTO_NOOVERLAP 1 diff --git a/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/cofb.h b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/cofb.h new file mode 100644 index 0000000..6a60e36 --- /dev/null +++ b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/cofb.h @@ -0,0 +1,62 @@ +#ifndef COFB_H_ +#define COFB_H_ + +#define DOUBLE_HALF_BLOCK(x) ({ \ + tmp0 = (x)[0]; \ + (x)[0] = (((x)[0] & 0x7f7f7f7f) << 1) | (((x)[0] & 0x80808080) >> 15); \ + (x)[0] |= ((x)[1] & 0x80808080) << 17; \ + (x)[1] = (((x)[1] & 0x7f7f7f7f) << 1) | (((x)[1] & 0x80808080) >> 15); \ + (x)[1] ^= (((tmp0 >> 7) & 1) * 27) << 24; \ +}) + +#define TRIPLE_HALF_BLOCK(x) ({ \ + tmp0 = (x)[0]; \ + tmp1 = (x)[1]; \ + (x)[0] = (((x)[0] & 0x7f7f7f7f) << 1) | (((x)[0] & 0x80808080) >> 15); \ + (x)[0] |= ((x)[1] & 0x80808080) << 17; \ + (x)[1] = (((x)[1] & 0x7f7f7f7f) << 1) | (((x)[1] & 0x80808080) >> 15); \ + (x)[1] ^= (((tmp0 >> 7) & 1) * 27) << 24; \ + (x)[0] ^= tmp0; \ + (x)[1] ^= tmp1; \ +}) + +#define G(x) ({ \ + tmp0 = (x)[0]; \ + tmp1 = (x)[1]; \ + (x)[0] = (x)[2]; \ + (x)[1] = (x)[3]; \ + (x)[2] = ((tmp0 & 0x7f7f7f7f) << 1) | ((tmp0 & 0x80808080) >> 15); \ + (x)[2] |= ((tmp1 & 0x80808080) << 17); \ + (x)[3] = ((tmp1 & 0x7f7f7f7f) << 1) | ((tmp1 & 0x80808080) >> 15); \ + (x)[3] |= ((tmp0 & 0x80808080) << 17); \ +}) + +#define XOR_BLOCK(x, y, z) ({ \ + (x)[0] = (y)[0] ^ (z)[0]; \ + (x)[1] = (y)[1] ^ (z)[1]; \ + (x)[2] = (y)[2] ^ (z)[2]; \ + (x)[3] = (y)[3] ^ (z)[3]; \ +}) + +#define XOR_TOP_BAR_BLOCK(x, y) ({ \ + (x)[0] ^= (y)[0]; \ + (x)[1] ^= (y)[1]; \ +}) + +#define RHO1(d, y, m, n) ({ \ + G(y); \ + padding(d,m,n); \ + XOR_BLOCK(d, d, y); \ +}) + +#define RHO(y, m, x, c, n) ({ \ + XOR_BLOCK(c, y, m); \ + RHO1(x, y, m, n); \ +}) + +#define RHO_PRIME(y, c, x, m, n) ({ \ + XOR_BLOCK(m, y, c); \ + RHO1(x, y, m, n); \ +}) + +#endif // COFB_H_ \ No newline at end of file diff --git a/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/encrypt.c b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/encrypt.c new file mode 100644 index 0000000..5f12a47 --- /dev/null +++ b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/encrypt.c @@ -0,0 +1,163 @@ +/******************************************************************************* +* Constant-time 32-bit implementation of the GIFT-COFB authenticated cipher. +* +* @author Alexandre Adomnicai, Nanyang Technological University, +* alexandre.adomnicai@ntu.edu.sg +* @date January 2020 +*******************************************************************************/ +#include //for memcpy +#include "api.h" +#include "cofb.h" +#include "giftb128.h" + +#define TAGBYTES CRYPTO_ABYTES +#define BLOCKBYTES CRYPTO_ABYTES +#define COFB_ENCRYPT 1 +#define COFB_DECRYPT 0 + +/**************************************************************************** +* 32-bit padding implementation. +****************************************************************************/ +static inline void padding(u32* d, const u32* s, const u32 no_of_bytes){ + u32 i; + if (no_of_bytes == 0) { + d[0] = 0x00000080; // little-endian + d[1] = 0x00000000; + d[2] = 0x00000000; + d[3] = 0x00000000; + } + else if (no_of_bytes < BLOCKBYTES) { + for (i = 0; i < no_of_bytes/4+1; i++) + d[i] = s[i]; + d[i-1] &= ~(0xffffffffL << (no_of_bytes % 4)*8); + d[i-1] |= 0x00000080L << (no_of_bytes % 4)*8; + for (; i < 4; i++) + d[i] = 0x00000000; + } + else { + d[0] = s[0]; + d[1] = s[1]; + d[2] = s[2]; + d[3] = s[3]; + } +} + +/**************************************************************************** +* Constant-time implementation of the GIFT-COFB authenticated cipher based on +* fixsliced GIFTb-128. Encryption/decryption is handled by the same function, +* depending on the 'encrypting' parameter (1/0). +****************************************************************************/ +int giftcofb_crypt(u8* out, const u8* key, const u8* nonce, const u8* ad, + u32 ad_len, const u8* in, u32 in_len, const int encrypting) { + + u32 tmp0, tmp1, emptyA, emptyM; + u32 offset[2], input[4], rkey[80]; + u8 Y[16]; + + if (!encrypting) { + if (in_len < TAGBYTES) + return -1; + in_len -= TAGBYTES; + } + + if (ad_len == 0) + emptyA = 1; + else + emptyA = 0; + + if (in_len == 0) + emptyM =1; + else + emptyM = 0; + + precompute_rkeys(rkey, key); + giftb128(Y, nonce, rkey); + offset[0] = ((u32*)Y)[0]; + offset[1] = ((u32*)Y)[1]; + + while (ad_len > BLOCKBYTES) { + RHO1(input, (u32*)Y, (u32*)ad, BLOCKBYTES); + DOUBLE_HALF_BLOCK(offset); + XOR_TOP_BAR_BLOCK(input, offset); + giftb128(Y, (u8*)input, rkey); + ad += BLOCKBYTES; + ad_len -= BLOCKBYTES; + } + + TRIPLE_HALF_BLOCK(offset); + if ((ad_len % BLOCKBYTES != 0) || (emptyA)) + TRIPLE_HALF_BLOCK(offset); + if (emptyM) { + TRIPLE_HALF_BLOCK(offset); + TRIPLE_HALF_BLOCK(offset); + } + + RHO1(input, (u32*)Y, (u32*)ad, ad_len); + XOR_TOP_BAR_BLOCK(input, offset); + giftb128(Y, (u8*)input, rkey); + + while (in_len > BLOCKBYTES) { + DOUBLE_HALF_BLOCK(offset); + if (encrypting) + RHO((u32*)Y, (u32*)in, input, (u32*)out, BLOCKBYTES); + else + RHO_PRIME((u32*)Y, (u32*)in, input, (u32*)out, BLOCKBYTES); + XOR_TOP_BAR_BLOCK(input, offset); + giftb128(Y, (u8*)input, rkey); + in += BLOCKBYTES; + out += BLOCKBYTES; + in_len -= BLOCKBYTES; + } + + if (!emptyM) { + TRIPLE_HALF_BLOCK(offset); + if(in_len % BLOCKBYTES != 0) + TRIPLE_HALF_BLOCK(offset); + if (encrypting) { + RHO((u32*)Y, (u32*)in, input, (u32*)out, in_len); + out += in_len; + } + else { + RHO_PRIME((u32*)Y, (u32*)in, input, (u32*)out, in_len); + in += in_len; + } + XOR_TOP_BAR_BLOCK(input, offset); + giftb128(Y, (u8*)input, rkey); + } + + if (encrypting) { + memcpy(out, Y, TAGBYTES); + return 0; + } + // decrypting + tmp0 = 0; + for(tmp1 = 0; tmp1 < TAGBYTES; tmp1++) + tmp0 |= in[tmp1] ^ Y[tmp1]; + return tmp0; +} + +/**************************************************************************** +* API required by the NIST for the LWC competition. +****************************************************************************/ +int crypto_aead_encrypt(unsigned char* c, unsigned long long* clen, + const unsigned char* m, unsigned long long mlen, + const unsigned char* ad, unsigned long long adlen, + const unsigned char* nsec, const unsigned char* npub, + const unsigned char* k) { + (void)nsec; + *clen = mlen + TAGBYTES; + return giftcofb_crypt(c, k, npub, ad, adlen, m, mlen, COFB_ENCRYPT); +} + +/**************************************************************************** +* API required by the NIST for the LWC competition. +****************************************************************************/ +int crypto_aead_decrypt(unsigned char* m, unsigned long long *mlen, + unsigned char* nsec, const unsigned char* c, + unsigned long long clen, const unsigned char* ad, + unsigned long long adlen, const unsigned char* npub, + const unsigned char *k) { + (void)nsec; + *mlen = clen - TAGBYTES; + return giftcofb_crypt(m, k, npub, ad, adlen, c, clen, COFB_DECRYPT); +} diff --git a/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/endian.h b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/endian.h new file mode 100644 index 0000000..4b3879a --- /dev/null +++ b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/endian.h @@ -0,0 +1,14 @@ +#ifndef ENDIAN_H_ +#define ENDIAN_H_ + +#define U32BIG(x) \ + ((((x) & 0x000000FF) << 24) | (((x) & 0x0000FF00) << 8) | \ + (((x) & 0x00FF0000) >> 8) | (((x) & 0xFF000000) >> 24)) + +#define U8BIG(x, y) \ + (x)[0] = (y) >> 24; \ + (x)[1] = ((y) >> 16) & 0xff; \ + (x)[2] = ((y) >> 8) & 0xff; \ + (x)[3] = (y) & 0xff; + +#endif // ENDIAN_H_ \ No newline at end of file diff --git a/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/giftb128.c b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/giftb128.c new file mode 100644 index 0000000..a1e31ed --- /dev/null +++ b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/giftb128.c @@ -0,0 +1,96 @@ +/******************************************************************************* +* Optimized constant-time implementation of the GIFTb-128 block cipher. +* +* @author Alexandre Adomnicai, Nanyang Technological University, +* alexandre.adomnicai@ntu.edu.sg +* +* @date January 2020 +*******************************************************************************/ +#include "endian.h" +#include "giftb128.h" +#include "key_schedule.h" + +/***************************************************************************** +* The round constants according to the fixsliced representation. +*****************************************************************************/ +const u32 rconst[40] = { + 0x10000008, 0x80018000, 0x54000002, 0x01010181, + 0x8000001f, 0x10888880, 0x6001e000, 0x51500002, + 0x03030180, 0x8000002f, 0x10088880, 0x60016000, + 0x41500002, 0x03030080, 0x80000027, 0x10008880, + 0x4001e000, 0x11500002, 0x03020180, 0x8000002b, + 0x10080880, 0x60014000, 0x01400002, 0x02020080, + 0x80000021, 0x10000080, 0x0001c000, 0x51000002, + 0x03010180, 0x8000002e, 0x10088800, 0x60012000, + 0x40500002, 0x01030080, 0x80000006, 0x10008808, + 0xc001a000, 0x14500002, 0x01020181, 0x8000001a +}; + +/***************************************************************************** +* The first 20 rkeys are computed using the classical representation before +* being rearranged into fixsliced representations depending on round numbers. +* The 60 remaining rkeys are directly computed in fixscliced representations. +*****************************************************************************/ +void precompute_rkeys(u32* rkey, const u8* key) { + u32 tmp; + //classical initialization + rkey[0] = U32BIG(((u32*)key)[3]); + rkey[1] = U32BIG(((u32*)key)[1]); + rkey[2] = U32BIG(((u32*)key)[2]); + rkey[3] = U32BIG(((u32*)key)[0]); + // classical keyschedule + for(int i = 0; i < 16; i+=2) { + rkey[i+4] = rkey[i+1]; + rkey[i+5] = KEY_UPDATE(rkey[i]); + } + // transposition to fixsliced representations + for(int i = 0; i < 20; i+=10) { + rkey[i] = REARRANGE_RKEY_0(rkey[i]); + rkey[i + 1] = REARRANGE_RKEY_0(rkey[i + 1]); + rkey[i + 2] = REARRANGE_RKEY_1(rkey[i + 2]); + rkey[i + 3] = REARRANGE_RKEY_1(rkey[i + 3]); + rkey[i + 4] = REARRANGE_RKEY_2(rkey[i + 4]); + rkey[i + 5] = REARRANGE_RKEY_2(rkey[i + 5]); + rkey[i + 6] = REARRANGE_RKEY_3(rkey[i + 6]); + rkey[i + 7] = REARRANGE_RKEY_3(rkey[i + 7]); + } + // keyschedule according to fixsliced representations + for(int i = 20; i < 80; i+=10) { + rkey[i] = rkey[i-19]; + rkey[i+1] = KEY_TRIPLE_UPDATE_0(rkey[i-20]); + rkey[i+2] = KEY_DOUBLE_UPDATE_1(rkey[i-17]); + rkey[i+3] = KEY_TRIPLE_UPDATE_1(rkey[i-18]); + rkey[i+4] = KEY_DOUBLE_UPDATE_2(rkey[i-15]); + rkey[i+5] = KEY_TRIPLE_UPDATE_2(rkey[i-16]); + rkey[i+6] = KEY_DOUBLE_UPDATE_3(rkey[i-13]); + rkey[i+7] = KEY_TRIPLE_UPDATE_3(rkey[i-14]); + rkey[i+8] = KEY_DOUBLE_UPDATE_4(rkey[i-11]); + rkey[i+9] = KEY_TRIPLE_UPDATE_4(rkey[i-12]); + SWAPMOVE(rkey[i], rkey[i], 0x00003333, 16); + SWAPMOVE(rkey[i], rkey[i], 0x55554444, 1); + SWAPMOVE(rkey[i+1], rkey[i+1], 0x55551100, 1); + } +} + +/***************************************************************************** +* Encryption of a single 128-bit block with GIFTb-128 (used in GIFT-COFB). +*****************************************************************************/ +void giftb128(u8* ctext, const u8* ptext, const u32* rkey) { + u32 tmp, state[4]; + state[0] = U32BIG(((u32*)ptext)[0]); + state[1] = U32BIG(((u32*)ptext)[1]); + state[2] = U32BIG(((u32*)ptext)[2]); + state[3] = U32BIG(((u32*)ptext)[3]); + QUINTUPLE_ROUND(state, rkey, rconst); + QUINTUPLE_ROUND(state, rkey + 10, rconst + 5); + QUINTUPLE_ROUND(state, rkey + 20, rconst + 10); + QUINTUPLE_ROUND(state, rkey + 30, rconst + 15); + QUINTUPLE_ROUND(state, rkey + 40, rconst + 20); + QUINTUPLE_ROUND(state, rkey + 50, rconst + 25); + QUINTUPLE_ROUND(state, rkey + 60, rconst + 30); + QUINTUPLE_ROUND(state, rkey + 70, rconst + 35); + U8BIG(ctext, state[0]); + U8BIG(ctext + 4, state[1]); + U8BIG(ctext + 8, state[2]); + U8BIG(ctext + 12, state[3]); +} diff --git a/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/giftb128.h b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/giftb128.h new file mode 100644 index 0000000..e1b8d10 --- /dev/null +++ b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/giftb128.h @@ -0,0 +1,88 @@ +#ifndef GIFT128_H_ +#define GIFT128_H_ + +typedef unsigned char u8; +typedef unsigned int u32; + +extern void precompute_rkeys(u32* rkeys, const u8* key); +extern void giftb128(u8* out, const u8* in, const u32* rkeys); + +#define ROR(x,y) \ + (((x) >> (y)) | ((x) << (32 - (y)))) +#define BYTE_ROR_2(x) \ + ((((x) >> 2) & 0x3f3f3f3f) | (((x) & 0x03030303) << 6)) +#define BYTE_ROR_4(x) \ + ((((x) >> 4) & 0x0f0f0f0f) | (((x) & 0x0f0f0f0f) << 4)) +#define BYTE_ROR_6(x) \ + ((((x) >> 6) & 0x03030303) | (((x) & 0x3f3f3f3f) << 2)) +#define HALF_ROR_4(x) \ + ((((x) >> 4) & 0x0fff0fff) | (((x) & 0x000f000f) << 12)) +#define HALF_ROR_8(x) \ + ((((x) >> 8) & 0x00ff00ff) | (((x) & 0x00ff00ff) << 8)) +#define HALF_ROR_12(x) \ + ((((x) >> 12)& 0x000f000f) | (((x) & 0x0fff0fff) << 4)) +#define NIBBLE_ROR_1(x) \ + ((((x) >> 1) & 0x77777777) | (((x) & 0x11111111) << 3)) +#define NIBBLE_ROR_2(x) \ + ((((x) >> 2) & 0x33333333) | (((x) & 0x33333333) << 2)) +#define NIBBLE_ROR_3(x) \ + ((((x) >> 3) & 0x11111111) | (((x) & 0x77777777) << 1)) + +#define SWAPMOVE(a, b, mask, n) \ + tmp = (b ^ (a >> n)) & mask; \ + b ^= tmp; \ + a ^= (tmp << n); + +#define SBOX(s0, s1, s2, s3) \ + s1 ^= s0 & s2; \ + s0 ^= s1 & s3; \ + s2 ^= s0 | s1; \ + s3 ^= s2; \ + s1 ^= s3; \ + s3 ^= 0xffffffff; \ + s2 ^= s0 & s1; + +#define QUINTUPLE_ROUND(state, rkey, rconst) ({ \ + SBOX(state[0], state[1], state[2], state[3]); \ + state[3] = NIBBLE_ROR_1(state[3]); \ + state[1] = NIBBLE_ROR_2(state[1]); \ + state[2] = NIBBLE_ROR_3(state[2]); \ + state[1] ^= (rkey)[0]; \ + state[2] ^= (rkey)[1]; \ + state[0] ^= (rconst)[0]; \ + SBOX(state[3], state[1], state[2], state[0]); \ + state[0] = HALF_ROR_4(state[0]); \ + state[1] = HALF_ROR_8(state[1]); \ + state[2] = HALF_ROR_12(state[2]); \ + state[1] ^= (rkey)[2]; \ + state[2] ^= (rkey)[3]; \ + state[3] ^= (rconst)[1]; \ + SBOX(state[0], state[1], state[2], state[3]); \ + state[3] = ROR(state[3], 16); \ + state[2] = ROR(state[2], 16); \ + SWAPMOVE(state[1], state[1], 0x55555555, 1); \ + SWAPMOVE(state[2], state[2], 0x00005555, 1); \ + SWAPMOVE(state[3], state[3], 0x55550000, 1); \ + state[1] ^= (rkey)[4]; \ + state[2] ^= (rkey)[5]; \ + state[0] ^= (rconst)[2]; \ + SBOX(state[3], state[1], state[2], state[0]); \ + state[0] = BYTE_ROR_6(state[0]); \ + state[1] = BYTE_ROR_4(state[1]); \ + state[2] = BYTE_ROR_2(state[2]); \ + state[1] ^= (rkey)[6]; \ + state[2] ^= (rkey)[7]; \ + state[3] ^= (rconst)[3]; \ + SBOX(state[0], state[1], state[2], state[3]); \ + state[3] = ROR(state[3], 24); \ + state[1] = ROR(state[1], 16); \ + state[2] = ROR(state[2], 8); \ + state[1] ^= (rkey)[8]; \ + state[2] ^= (rkey)[9]; \ + state[0] ^= (rconst)[4]; \ + state[0] ^= state[3]; \ + state[3] ^= state[0]; \ + state[0] ^= state[3]; \ +}) + +#endif // GIFT128_H_ \ No newline at end of file diff --git a/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/key_schedule.h b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/key_schedule.h new file mode 100644 index 0000000..3965a44 --- /dev/null +++ b/gift-cofb/Implementations/crypto_aead/giftcofb128v1/opt32/key_schedule.h @@ -0,0 +1,70 @@ +#ifndef KEYSCHEDULE_H_ +#define KEYSCHEDULE_H_ + +#define REARRANGE_RKEY_0(x) ({ \ + SWAPMOVE(x, x, 0x00550055, 9); \ + SWAPMOVE(x, x, 0x000f000f, 12); \ + SWAPMOVE(x, x, 0x00003333, 18); \ + SWAPMOVE(x, x, 0x000000ff, 24); \ +}) + +#define REARRANGE_RKEY_1(x) ({ \ + SWAPMOVE(x, x, 0x11111111, 3); \ + SWAPMOVE(x, x, 0x03030303, 6); \ + SWAPMOVE(x, x, 0x000f000f, 12); \ + SWAPMOVE(x, x, 0x000000ff, 24); \ +}) + +#define REARRANGE_RKEY_2(x) ({ \ + SWAPMOVE(x, x, 0x0000aaaa, 15); \ + SWAPMOVE(x, x, 0x00003333, 18); \ + SWAPMOVE(x, x, 0x0000f0f0, 12); \ + SWAPMOVE(x, x, 0x000000ff, 24); \ +}) + +#define REARRANGE_RKEY_3(x) ({ \ + SWAPMOVE(x, x, 0x0a0a0a0a, 3); \ + SWAPMOVE(x, x, 0x00cc00cc, 6); \ + SWAPMOVE(x, x, 0x0000f0f0, 12); \ + SWAPMOVE(x, x, 0x000000ff, 24); \ +}) + +#define KEY_UPDATE(x) \ + (((x) >> 12) & 0x0000000f) | (((x) & 0x00000fff) << 4) | \ + (((x) >> 2) & 0x3fff0000) | (((x) & 0x00030000) << 14) + +#define KEY_TRIPLE_UPDATE_0(x) \ + (ROR((x) & 0x33333333, 24) | ROR((x) & 0xcccccccc, 16)) + +#define KEY_DOUBLE_UPDATE_1(x) \ + ((((x) >> 4) & 0x0f000f00) | (((x) & 0x0f000f00) << 4) | \ + (((x) >> 6) & 0x00030003) | (((x) & 0x003f003f) << 2)) + +#define KEY_TRIPLE_UPDATE_1(x) \ + ((((x) >> 6) & 0x03000300) | (((x) & 0x3f003f00) << 2) | \ + (((x) >> 5) & 0x00070007) | (((x) & 0x001f001f) << 3)) + +#define KEY_DOUBLE_UPDATE_2(x) \ + (ROR((x) & 0xaaaaaaaa, 24) | ROR((x) & 0x55555555, 16)) + +#define KEY_TRIPLE_UPDATE_2(x) \ + (ROR((x) & 0x55555555, 24) | ROR((x) & 0xaaaaaaaa, 20)) + +#define KEY_DOUBLE_UPDATE_3(x) \ + ((((x) >> 2) & 0x03030303) | (((x) & 0x03030303) << 2) | \ + (((x) >> 1) & 0x70707070) | (((x) & 0x10101010) << 3)) + +#define KEY_TRIPLE_UPDATE_3(x) \ + ((((x) >> 18) & 0x00003030) | (((x) & 0x01010101) << 3) | \ + (((x) >> 14) & 0x0000c0c0) | (((x) & 0x0000e0e0) << 15)| \ + (((x) >> 1) & 0x07070707) | (((x) & 0x00001010) << 19)) + +#define KEY_DOUBLE_UPDATE_4(x) \ + ((((x) >> 4) & 0x0fff0000) | (((x) & 0x000f0000) << 12) | \ + (((x) >> 8) & 0x000000ff) | (((x) & 0x000000ff) << 8)) + +#define KEY_TRIPLE_UPDATE_4(x) \ + ((((x) >> 6) & 0x03ff0000) | (((x) & 0x003f0000) << 10) | \ + (((x) >> 4) & 0x00000fff) | (((x) & 0x0000000f) << 12)) + +#endif // KEYSCHEDULE_H_ \ No newline at end of file -- libgit2 0.26.0