packages feed

hwsl2-0.1.1.3: src/sl2-inl.h

#pragma once

#include "gf2p127-inl.h"

typedef gf2p127_t sl2_t[2][2];

static inline
_Bool sl2_eq(sl2_t a, sl2_t b) {
  return gf2p127_eq(a[0][0], b[0][0]) &&
         gf2p127_eq(a[0][1], b[0][1]) &&
         gf2p127_eq(a[1][0], b[1][0]) &&
         gf2p127_eq(a[1][1], b[1][1]);
}

static inline
void sl2_copy(sl2_t dst, sl2_t src) {
  dst[0][0] = src[0][0];
  dst[0][1] = src[0][1];
  dst[1][0] = src[1][0];
  dst[1][1] = src[1][1];
}

static inline
void sl2_mul_bit_left(sl2_t b, int bit) {
  // A: {00 = 10, 01 = 01, 10 = 01, 11 = 00}
  // B: {00 = 10, 01 = 11, 10 = 01, 11 = 01}
  gf2p127_t b00 = b[0][0];
  gf2p127_t b10 = b[1][0];
  gf2p127_t b01 = b[0][1];
  gf2p127_t b11 = b[1][1];
  b[0][0] = gf2p127_zero();
  b[0][1] = gf2p127_zero();
  b[1][0] = gf2p127_add(b00, b[bit][0]);
  b[1][1] = gf2p127_add(b01, b[bit][1]);
  b[0][0] = gf2p127_add(b10, gf2p127_mul_10_left(b[1][0]));
  b[0][1] = gf2p127_add(b11, gf2p127_mul_10_left(b[1][1]));
}

static inline
void sl2_mul_bits_left(sl2_t b, unsigned char byte) {
  sl2_mul_bit_left(b, (byte >> 0) & 1);
  sl2_mul_bit_left(b, (byte >> 1) & 1);
  sl2_mul_bit_left(b, (byte >> 2) & 1);
  sl2_mul_bit_left(b, (byte >> 3) & 1);
  sl2_mul_bit_left(b, (byte >> 4) & 1);
  sl2_mul_bit_left(b, (byte >> 5) & 1);
  sl2_mul_bit_left(b, (byte >> 6) & 1);
  sl2_mul_bit_left(b, (byte >> 7) & 1);
}

static inline
void sl2_mul_bit_right(sl2_t a, int bit) {
  // A: {00 = 10, 01 = 01, 10 = 01, 11 = 00}
  // B: {00 = 10, 01 = 11, 10 = 01, 11 = 01}
  gf2p127_t a00 = a[0][0];
  gf2p127_t a10 = a[1][0];
  gf2p127_t a01 = a[0][1];
  gf2p127_t a11 = a[1][1];
  a[0][1] = gf2p127_zero();
  a[1][1] = gf2p127_zero();
  a[0][0] = gf2p127_add(gf2p127_mul_10(a00), a01);
  a[1][0] = gf2p127_add(gf2p127_mul_10(a10), a11);
  a[0][1] = gf2p127_add(a00, a[0][!bit]);
  a[1][1] = gf2p127_add(a10, a[1][!bit]);
}

static inline
void sl2_mul_bits_right(sl2_t a, unsigned char byte) {
  sl2_mul_bit_right(a, (byte >> 7) & 1);
  sl2_mul_bit_right(a, (byte >> 6) & 1);
  sl2_mul_bit_right(a, (byte >> 5) & 1);
  sl2_mul_bit_right(a, (byte >> 4) & 1);
  sl2_mul_bit_right(a, (byte >> 3) & 1);
  sl2_mul_bit_right(a, (byte >> 2) & 1);
  sl2_mul_bit_right(a, (byte >> 1) & 1);
  sl2_mul_bit_right(a, (byte >> 0) & 1);
}

static inline
void sl2_mul(sl2_t c, sl2_t a, sl2_t b) {
  // Strassen algorithm
  gf2p127_t m0, m1, m2, m3, m4, m5, m6;
  m0 = gf2p127_mul(gf2p127_add(a[0][0], a[1][1]),
                   gf2p127_add(b[0][0], b[1][1]));
  m1 = gf2p127_mul(gf2p127_add(a[1][0], a[1][1]), b[0][0]);
  m2 = gf2p127_mul(a[0][0], gf2p127_add(b[0][1], b[1][1]));
  m3 = gf2p127_mul(a[1][1], gf2p127_add(b[1][0], b[0][0]));
  m4 = gf2p127_mul(gf2p127_add(a[0][0], a[0][1]), b[1][1]);
  m5 = gf2p127_mul(gf2p127_add(a[1][0], a[0][0]),
                   gf2p127_add(b[0][0], b[0][1]));
  m6 = gf2p127_mul(gf2p127_add(a[0][1], a[1][1]),
                   gf2p127_add(b[1][0], b[1][1]));
  c[0][0] = gf2p127_add(gf2p127_add(m0, m3), gf2p127_add(m4, m6));
  c[0][1] = gf2p127_add(m2, m4);
  c[1][0] = gf2p127_add(m1, m3);
  c[1][1] = gf2p127_add(gf2p127_add(m0, m1), gf2p127_add(m2, m5));
}

static inline
void sl2_mul_byte_left(sl2_t b, unsigned char byte, sl2_t m[256]) {
  sl2_mul(m[byte], b, b);
}

static inline
void sl2_mul_byte_right(sl2_t a, unsigned char byte, sl2_t m[256]) {
  sl2_mul(a, m[byte], a);
}

static inline
void sl2_init(sl2_t m[2]) {
  m[0][0][0] = gf2p127_from_int(2);
  m[0][0][1] = gf2p127_from_int(1);
  m[0][1][0] = gf2p127_from_int(1);
  m[0][1][1] = gf2p127_from_int(0);
  m[1][0][0] = gf2p127_from_int(2);
  m[1][0][1] = gf2p127_from_int(3);
  m[1][1][0] = gf2p127_from_int(1);
  m[1][1][1] = gf2p127_from_int(1);
}

static inline
void sl2_unit(sl2_t a) {
  a[0][0] = gf2p127_from_int(1);
  a[0][1] = gf2p127_from_int(0);
  a[1][0] = gf2p127_from_int(0);
  a[1][1] = gf2p127_from_int(1);
}

static inline
char *sl2_hex(char *buf, sl2_t a) {
  gf2p127_hex(&buf[0],  a[0][0]);
  gf2p127_hex(&buf[32], a[0][1]);
  gf2p127_hex(&buf[64], a[1][0]);
  gf2p127_hex(&buf[96], a[1][1]);
  return buf;
}

static const unsigned char b64[64] =
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";

static const unsigned char unb64[256] = {
  ['A'] =  0,  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,
  ['a'] = 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,
  ['0'] = 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
  ['-'] = 62, ['_'] = 63
};

static inline
void sl2_serialize(sl2_t m, unsigned char buf[86]) {

  int i, j;
  unsigned char a, b, c, *data = (unsigned char *)m;

  for (i = j = 0; i <= 64 - 3; i += 3, j += 4) {
    a = data[i + 0];
    b = data[i + 1];
    c = data[i + 2];
    buf[j + 0] = b64[a >> 2];
    buf[j + 1] = b64[((0x03 & a) << 4) + (b >> 4)];
    buf[j + 2] = b64[((0x0f & b) << 2) + (c >> 6)];
    buf[j + 3] = b64[0x3f & c];
  }

  buf[84] = b64[data[i] >> 2];
  buf[85] = b64[(0x3 & data[i]) << 4];

}

static inline
void sl2_unserialize(sl2_t m, unsigned char buf[86]) {

  int i, j;
  unsigned char a, b, c, d, *data = (unsigned char *)m;

  for (i = j = 0; i <= 86 - 4; i += 4, j += 3) {
    a = unb64[buf[i + 0]];
    b = unb64[buf[i + 1]];
    c = unb64[buf[i + 2]];
    d = unb64[buf[i + 3]];
    data[j + 0] = (a << 2) | (b >> 4);
    data[j + 1] = (b << 4) | (c >> 2);
    data[j + 2] = (c << 6) | (d);
  }

  data[63] = (unb64[buf[i]] << 2) | (unb64[buf[i + 1]] >> 4);

}