permutations.h 2.68 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
#ifndef PERMUTATIONS_H_
#define PERMUTATIONS_H_

#ifdef DEBUG
#include <stdio.h>
#endif

typedef unsigned char u8;
typedef unsigned long long u64;

typedef struct {
  u64 x0, x1, x2, x3, x4;
} state;

static inline void printstate(const char* text, const state s) {
#ifdef DEBUG
  printf("%s\n", text);
  printf("  x0=%016llx\n", s.x0);
  printf("  x1=%016llx\n", s.x1);
  printf("  x2=%016llx\n", s.x2);
  printf("  x3=%016llx\n", s.x3);
  printf("  x4=%016llx\n", s.x4);
#else
  // disable warning about unused parameters
  (void)text;
  (void)s;
#endif
}

static inline u64 BYTES_TO_U64(const u8* bytes, int n) {
  int i;
  u64 x = 0;
  for (i = 0; i < n; i++) x |= ((u64)bytes[i]) << (56 - 8 * i);
  return x;
}

static inline void U64_TO_BYTES(u8* bytes, const u64 x, int n) {
  int i;
  for (i = 0; i < n; i++) bytes[i] = (u8)(x >> (56 - 8 * i));
}

static inline u64 BYTE_MASK(int n) {
  int i;
  u64 x = 0;
  for (i = 0; i < n; i++) x |= 0xffull << (56 - 8 * i);
  return x;
}

static inline u64 ROTR64(u64 x, int n) { return (x << (64 - n)) | (x >> n); }

static inline void ROUND(u8 C, state* p) {
  state s = *p;
  state t;
  // addition of round constant
  s.x2 ^= C;
  printstate(" addition of round constant:", s);
  // substitution layer
  s.x0 ^= s.x4;
  s.x4 ^= s.x3;
  s.x2 ^= s.x1;
  // start of keccak s-box
  t.x0 = ~s.x0;
  t.x1 = ~s.x1;
  t.x2 = ~s.x2;
  t.x3 = ~s.x3;
  t.x4 = ~s.x4;
  t.x0 &= s.x1;
  t.x1 &= s.x2;
  t.x2 &= s.x3;
  t.x3 &= s.x4;
  t.x4 &= s.x0;
  s.x0 ^= t.x1;
  s.x1 ^= t.x2;
  s.x2 ^= t.x3;
  s.x3 ^= t.x4;
  s.x4 ^= t.x0;
  // end of keccak s-box
  s.x1 ^= s.x0;
  s.x0 ^= s.x4;
  s.x3 ^= s.x2;
  s.x2 = ~s.x2;
  printstate(" substitution layer:", s);
  // linear diffusion layer
  s.x0 ^= ROTR64(s.x0, 19) ^ ROTR64(s.x0, 28);
  s.x1 ^= ROTR64(s.x1, 61) ^ ROTR64(s.x1, 39);
  s.x2 ^= ROTR64(s.x2, 1) ^ ROTR64(s.x2, 6);
  s.x3 ^= ROTR64(s.x3, 10) ^ ROTR64(s.x3, 17);
  s.x4 ^= ROTR64(s.x4, 7) ^ ROTR64(s.x4, 41);
  printstate(" linear diffusion layer:", s);
  *p = s;
}

static inline void P12(state* s) {
  printstate(" permutation input:", *s);
  ROUND(0xf0, s);
  ROUND(0xe1, s);
  ROUND(0xd2, s);
  ROUND(0xc3, s);
  ROUND(0xb4, s);
  ROUND(0xa5, s);
  ROUND(0x96, s);
  ROUND(0x87, s);
  ROUND(0x78, s);
  ROUND(0x69, s);
  ROUND(0x5a, s);
  ROUND(0x4b, s);
}

static inline void P8(state* s) {
  printstate(" permutation input:", *s);
  ROUND(0xb4, s);
  ROUND(0xa5, s);
  ROUND(0x96, s);
  ROUND(0x87, s);
  ROUND(0x78, s);
  ROUND(0x69, s);
  ROUND(0x5a, s);
  ROUND(0x4b, s);
}

static inline void P6(state* s) {
  printstate(" permutation input:", *s);
  ROUND(0x96, s);
  ROUND(0x87, s);
  ROUND(0x78, s);
  ROUND(0x69, s);
  ROUND(0x5a, s);
  ROUND(0x4b, s);
}

#endif  // PERMUTATIONS_H_