keccak-fast.c

Minimal SIMD keccak implementation
git clone git://git.finwo.net/lib/keccak-fast.c
Log | Files | Refs | README | LICENSE

scalar-perm.h (5733B)


      1 #ifndef FINWO_SCALAR_PERM_H
      2 #define FINWO_SCALAR_PERM_H
      3 
      4 /* Keccak-p[1600] with the 25 lanes held in named locals rather than an indexed
      5    array, so the scheduler can keep them in registers; theta is fused into the
      6    previous round's chi (prepareTheta) and the round loop is unrolled 4x. */
      7 
      8 #define KFP_LOAD(P, S) \
      9   P##0 = S[0]; \
     10   P##1 = S[1]; \
     11   P##2 = S[2]; \
     12   P##3 = S[3]; \
     13   P##4 = S[4]; \
     14   P##5 = S[5]; \
     15   P##6 = S[6]; \
     16   P##7 = S[7]; \
     17   P##8 = S[8]; \
     18   P##9 = S[9]; \
     19   P##10 = S[10]; \
     20   P##11 = S[11]; \
     21   P##12 = S[12]; \
     22   P##13 = S[13]; \
     23   P##14 = S[14]; \
     24   P##15 = S[15]; \
     25   P##16 = S[16]; \
     26   P##17 = S[17]; \
     27   P##18 = S[18]; \
     28   P##19 = S[19]; \
     29   P##20 = S[20]; \
     30   P##21 = S[21]; \
     31   P##22 = S[22]; \
     32   P##23 = S[23]; \
     33   P##24 = S[24]; \
     34 
     35 #define KFP_STORE(S, P) \
     36   S[0] = P##0; \
     37   S[1] = P##1; \
     38   S[2] = P##2; \
     39   S[3] = P##3; \
     40   S[4] = P##4; \
     41   S[5] = P##5; \
     42   S[6] = P##6; \
     43   S[7] = P##7; \
     44   S[8] = P##8; \
     45   S[9] = P##9; \
     46   S[10] = P##10; \
     47   S[11] = P##11; \
     48   S[12] = P##12; \
     49   S[13] = P##13; \
     50   S[14] = P##14; \
     51   S[15] = P##15; \
     52   S[16] = P##16; \
     53   S[17] = P##17; \
     54   S[18] = P##18; \
     55   S[19] = P##19; \
     56   S[20] = P##20; \
     57   S[21] = P##21; \
     58   S[22] = P##22; \
     59   S[23] = P##23; \
     60   S[24] = P##24; \
     61 
     62 #define KFP_INIT_C(SRC) \
     63   c0 = SRC##0 ^ SRC##5 ^ SRC##10 ^ SRC##15 ^ SRC##20; \
     64   c1 = SRC##1 ^ SRC##6 ^ SRC##11 ^ SRC##16 ^ SRC##21; \
     65   c2 = SRC##2 ^ SRC##7 ^ SRC##12 ^ SRC##17 ^ SRC##22; \
     66   c3 = SRC##3 ^ SRC##8 ^ SRC##13 ^ SRC##18 ^ SRC##23; \
     67   c4 = SRC##4 ^ SRC##9 ^ SRC##14 ^ SRC##19 ^ SRC##24; \
     68 
     69 #define KFP_R(SRC, DST, RCIDX) \
     70   d0 = c4 ^ rol(c1, 1); \
     71   d1 = c0 ^ rol(c2, 1); \
     72   d2 = c1 ^ rol(c3, 1); \
     73   d3 = c2 ^ rol(c4, 1); \
     74   d4 = c3 ^ rol(c0, 1); \
     75   SRC##0 ^= d0; \
     76   b0 = SRC##0; \
     77   SRC##6 ^= d1; \
     78   b1 = rol(SRC##6, 44); \
     79   SRC##12 ^= d2; \
     80   b2 = rol(SRC##12, 43); \
     81   SRC##18 ^= d3; \
     82   b3 = rol(SRC##18, 21); \
     83   SRC##24 ^= d4; \
     84   b4 = rol(SRC##24, 14); \
     85   DST##0 = b0 ^ ((~b1) & b2); \
     86   DST##1 = b1 ^ ((~b2) & b3); \
     87   DST##2 = b2 ^ ((~b3) & b4); \
     88   DST##3 = b3 ^ ((~b4) & b0); \
     89   DST##4 = b4 ^ ((~b0) & b1); \
     90   DST##0 ^= RC[RCIDX]; \
     91   c0 = DST##0; \
     92   c1 = DST##1; \
     93   c2 = DST##2; \
     94   c3 = DST##3; \
     95   c4 = DST##4; \
     96   SRC##3 ^= d3; \
     97   b5 = rol(SRC##3, 28); \
     98   SRC##9 ^= d4; \
     99   b6 = rol(SRC##9, 20); \
    100   SRC##10 ^= d0; \
    101   b7 = rol(SRC##10, 3); \
    102   SRC##16 ^= d1; \
    103   b8 = rol(SRC##16, 45); \
    104   SRC##22 ^= d2; \
    105   b9 = rol(SRC##22, 61); \
    106   DST##5 = b5 ^ ((~b6) & b7); \
    107   DST##6 = b6 ^ ((~b7) & b8); \
    108   DST##7 = b7 ^ ((~b8) & b9); \
    109   DST##8 = b8 ^ ((~b9) & b5); \
    110   DST##9 = b9 ^ ((~b5) & b6); \
    111   c0 ^= DST##5; \
    112   c1 ^= DST##6; \
    113   c2 ^= DST##7; \
    114   c3 ^= DST##8; \
    115   c4 ^= DST##9; \
    116   SRC##1 ^= d1; \
    117   b10 = rol(SRC##1, 1); \
    118   SRC##7 ^= d2; \
    119   b11 = rol(SRC##7, 6); \
    120   SRC##13 ^= d3; \
    121   b12 = rol(SRC##13, 25); \
    122   SRC##19 ^= d4; \
    123   b13 = rol(SRC##19, 8); \
    124   SRC##20 ^= d0; \
    125   b14 = rol(SRC##20, 18); \
    126   DST##10 = b10 ^ ((~b11) & b12); \
    127   DST##11 = b11 ^ ((~b12) & b13); \
    128   DST##12 = b12 ^ ((~b13) & b14); \
    129   DST##13 = b13 ^ ((~b14) & b10); \
    130   DST##14 = b14 ^ ((~b10) & b11); \
    131   c0 ^= DST##10; \
    132   c1 ^= DST##11; \
    133   c2 ^= DST##12; \
    134   c3 ^= DST##13; \
    135   c4 ^= DST##14; \
    136   SRC##4 ^= d4; \
    137   b15 = rol(SRC##4, 27); \
    138   SRC##5 ^= d0; \
    139   b16 = rol(SRC##5, 36); \
    140   SRC##11 ^= d1; \
    141   b17 = rol(SRC##11, 10); \
    142   SRC##17 ^= d2; \
    143   b18 = rol(SRC##17, 15); \
    144   SRC##23 ^= d3; \
    145   b19 = rol(SRC##23, 56); \
    146   DST##15 = b15 ^ ((~b16) & b17); \
    147   DST##16 = b16 ^ ((~b17) & b18); \
    148   DST##17 = b17 ^ ((~b18) & b19); \
    149   DST##18 = b18 ^ ((~b19) & b15); \
    150   DST##19 = b19 ^ ((~b15) & b16); \
    151   c0 ^= DST##15; \
    152   c1 ^= DST##16; \
    153   c2 ^= DST##17; \
    154   c3 ^= DST##18; \
    155   c4 ^= DST##19; \
    156   SRC##2 ^= d2; \
    157   b20 = rol(SRC##2, 62); \
    158   SRC##8 ^= d3; \
    159   b21 = rol(SRC##8, 55); \
    160   SRC##14 ^= d4; \
    161   b22 = rol(SRC##14, 39); \
    162   SRC##15 ^= d0; \
    163   b23 = rol(SRC##15, 41); \
    164   SRC##21 ^= d1; \
    165   b24 = rol(SRC##21, 2); \
    166   DST##20 = b20 ^ ((~b21) & b22); \
    167   DST##21 = b21 ^ ((~b22) & b23); \
    168   DST##22 = b22 ^ ((~b23) & b24); \
    169   DST##23 = b23 ^ ((~b24) & b20); \
    170   DST##24 = b24 ^ ((~b20) & b21); \
    171   c0 ^= DST##20; \
    172   c1 ^= DST##21; \
    173   c2 ^= DST##22; \
    174   c3 ^= DST##23; \
    175   c4 ^= DST##24; \
    176 
    177 #define KFP_R2(SRC, DST, I) KFP_R(SRC, DST, I) KFP_R(DST, SRC, I + 1)
    178 #define KFP_R4(SRC, DST, I) KFP_R2(SRC, DST, I) KFP_R2(SRC, DST, I + 2)
    179 #define KFP_R12(SRC, DST, I) \
    180   KFP_R4(SRC, DST, I) KFP_R4(SRC, DST, I + 4) KFP_R4(SRC, DST, I + 8)
    181 
    182 #define KFP_DECL(P)                                                            \
    183   uint64_t P##0, P##1, P##2, P##3, P##4, P##5, P##6, P##7, P##8, P##9,         \
    184       P##10, P##11, P##12, P##13, P##14, P##15, P##16, P##17, P##18, P##19,    \
    185       P##20, P##21, P##22, P##23, P##24
    186 
    187 #define KFP_BODY(ROUNDS)                                                       \
    188   uint64_t *s = (uint64_t *)state;                                             \
    189   KFP_DECL(a);                                                                 \
    190   KFP_DECL(e);                                                                 \
    191   KFP_DECL(b);                                                                 \
    192   uint64_t c0, c1, c2, c3, c4, d0, d1, d2, d3, d4;                             \
    193   KFP_LOAD(a, s)                                                               \
    194   KFP_INIT_C(a)                                                                \
    195   ROUNDS                                                                       \
    196   KFP_STORE(s, a)
    197 
    198 static inline void keccakf(void *state) {
    199   KFP_BODY(for (int i = 0; i < 24; i += 4) { KFP_R4(a, e, i) })
    200 }
    201 
    202 static inline void keccak12(void *state) {
    203   KFP_BODY(for (int i = 12; i < 24; i += 4) { KFP_R4(a, e, i) })
    204 }
    205 
    206 #endif /* FINWO_SCALAR_PERM_H */