permutations.h 4.6 KB
Newer Older
lwc-tester committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
#ifndef PERMUTATIONS_H_
#define PERMUTATIONS_H_

#include "endian.h"

typedef unsigned char u8;
typedef unsigned int u32;
typedef unsigned long long u64;

typedef struct {
  u32 e;
  u32 o;
} u32_2;

#define EXT_BYTE64(x, n) ((u8)((u64)(x) >> (8 * (7 - (n)))))
#define INS_BYTE64(x, n) ((u64)(x) << (8 * (7 - (n))))
#define ROTR32(x, n) (((x) >> (n)) | ((x) << (32 - (n))))

// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
#define to_bit_interleaving(out, in)                          \
  do {                                                        \
    u32 hi = (in) >> 32;                                      \
    u32 lo = (u32)(in);                                       \
    u32 r0, r1;                                               \
    r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1); \
    r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2); \
    r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4); \
    r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8); \
    r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1); \
    r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2); \
    r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4); \
    r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8); \
    (out).e = (lo & 0x0000FFFF) | (hi << 16);                 \
    (out).o = (lo >> 16) | (hi & 0xFFFF0000);                 \
  } while (0)

// Credit to Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002
#define from_bit_interleaving(out, in)                        \
  do {                                                        \
    u32 lo = ((in).e & 0x0000FFFF) | ((in).o << 16);          \
    u32 hi = ((in).e >> 16) | ((in).o & 0xFFFF0000);          \
    u32 r0, r1;                                               \
    r0 = (lo ^ (lo >> 8)) & 0x0000FF00, lo ^= r0 ^ (r0 << 8); \
    r0 = (lo ^ (lo >> 4)) & 0x00F000F0, lo ^= r0 ^ (r0 << 4); \
    r0 = (lo ^ (lo >> 2)) & 0x0C0C0C0C, lo ^= r0 ^ (r0 << 2); \
    r0 = (lo ^ (lo >> 1)) & 0x22222222, lo ^= r0 ^ (r0 << 1); \
    r1 = (hi ^ (hi >> 8)) & 0x0000FF00, hi ^= r1 ^ (r1 << 8); \
    r1 = (hi ^ (hi >> 4)) & 0x00F000F0, hi ^= r1 ^ (r1 << 4); \
    r1 = (hi ^ (hi >> 2)) & 0x0C0C0C0C, hi ^= r1 ^ (r1 << 2); \
    r1 = (hi ^ (hi >> 1)) & 0x22222222, hi ^= r1 ^ (r1 << 1); \
    out = (u64)hi << 32 | lo;                                 \
  } while (0)

#define ROUND(C_e, C_o) \
  do { \
    /* round constant */ \
    x2.e ^= C_e;              x2.o ^= C_o; \
    /* s-box layer */ \
    x0.e ^= x4.e;             x0.o ^= x4.o; \
    x4.e ^= x3.e;             x4.o ^= x3.o; \
    x2.e ^= x1.e;             x2.o ^= x1.o; \
    t0.e = x0.e & (~x4.e);    t0.o = x0.o & (~x4.o); \
    x0.e ^= x2.e & (~x1.e);   x0.o ^= x2.o & (~x1.o); \
    x2.e ^= x4.e & (~x3.e);   x2.o ^= x4.o & (~x3.o); \
    x4.e ^= x1.e & (~x0.e);   x4.o ^= x1.o & (~x0.o); \
    x1.e ^= x3.e & (~x2.e);   x1.o ^= x3.o & (~x2.o); \
    x3.e ^= t0.e;             x3.o ^= t0.o; \
    x1.e ^= x0.e;             x1.o ^= x0.o; \
    x3.e ^= x2.e;             x3.o ^= x2.o; \
    x0.e ^= x4.e;             x0.o ^= x4.o; \
    /* linear layer */ \
    t0.e  = x0.e ^ ROTR32(x0.o, 4); \
    t0.o  = x0.o ^ ROTR32(x0.e, 5); \
    x0.e ^= ROTR32(t0.o, 9); \
    x0.o ^= ROTR32(t0.e, 10); \
    t0.e  = x1.e ^ ROTR32(x1.e, 11); \
    t0.o  = x1.o ^ ROTR32(x1.o, 11); \
    x1.e ^= ROTR32(t0.o, 19); \
    x1.o ^= ROTR32(t0.e, 20); \
    t0.e  = x2.e ^ ROTR32(x2.o, 2); \
    t0.o  = x2.o ^ ROTR32(x2.e, 3); \
    x2.e ^= t0.o; \
    x2.o ^= ROTR32(t0.e, 1); \
    t0.e  = x3.e ^ ROTR32(x3.o, 3); \
    t0.o  = x3.o ^ ROTR32(x3.e, 4); \
    x3.e ^= ROTR32(t0.e, 5); \
    x3.o ^= ROTR32(t0.o, 5); \
    t0.e  = x4.e ^ ROTR32(x4.e, 17); \
    t0.o  = x4.o ^ ROTR32(x4.o, 17); \
    x4.e ^= ROTR32(t0.o, 3); \
    x4.o ^= ROTR32(t0.e, 4); \
    x2.e = ~x2.e;             x2.o = ~x2.o; \
  } while(0)

#define P12()        \
  do {               \
    ROUND(0xc, 0xc); \
    ROUND(0x9, 0xc); \
    ROUND(0xc, 0x9); \
    ROUND(0x9, 0x9); \
    ROUND(0x6, 0xc); \
    ROUND(0x3, 0xc); \
    ROUND(0x6, 0x9); \
    ROUND(0x3, 0x9); \
    ROUND(0xc, 0x6); \
    ROUND(0x9, 0x6); \
    ROUND(0xc, 0x3); \
    ROUND(0x9, 0x3); \
  } while (0)

#define P8()         \
  do {               \
    ROUND(0x6, 0xc); \
    ROUND(0x3, 0xc); \
    ROUND(0x6, 0x9); \
    ROUND(0x3, 0x9); \
    ROUND(0xc, 0x6); \
    ROUND(0x9, 0x6); \
    ROUND(0xc, 0x3); \
    ROUND(0x9, 0x3); \
  } while (0)

#define P6()         \
  do {               \
    ROUND(0x6, 0x9); \
    ROUND(0x3, 0x9); \
    ROUND(0xc, 0x6); \
    ROUND(0x9, 0x6); \
    ROUND(0xc, 0x3); \
    ROUND(0x9, 0x3); \
  } while (0)

#endif  // PERMUTATIONS_H_