/*
 * cifra - embedded cryptography library
 * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
 *
 * To the extent possible under law, the author(s) have dedicated all
 * copyright and related and neighboring rights to this software to the
 * public domain worldwide. This software is distributed without any
 * warranty.
 *
 * You should have received a copy of the CC0 Public Domain Dedication
 * along with this software. If not, see
 * <http://creativecommons.org/publicdomain/zero/1.0/>.
 */

#ifndef BITOPS_H
#define BITOPS_H

#include <stdint.h>
#include <stddef.h>

#ifdef _WINDOWS
#include <intrin.h>
#endif

/* Assorted bitwise and common operations used in ciphers. */

/** Circularly rotate right x by n bits.
 *  0 > n > 32. */
static inline uint32_t rotr32(uint32_t x, unsigned n)
{
  return (x >> n) | (x << (32 - n));
}

/** Circularly rotate left x by n bits.
 *  0 > n > 32. */
static inline uint32_t rotl32(uint32_t x, unsigned n)
{
  return (x << n) | (x >> (32 - n));
}

/** Circularly rotate right x by n bits.
 *  0 > n > 64. */
static inline uint64_t rotr64(uint64_t x, unsigned n)
{
  return (x >> n) | (x << (64 - n));
}

/** Circularly rotate left x by n bits.
 *  0 > n > 64. */
static inline uint64_t rotl64(uint64_t x, unsigned n)
{
  return (x << n) | (x >> (64 - n));
}

/** Read 4 bytes from buf, as a 32-bit big endian quantity. */
static inline uint32_t read32_be(const uint8_t buf[4])
{
  return ((uint32_t)buf[0] << 24) |
         ((uint32_t)buf[1] << 16) |
         ((uint32_t)buf[2] << 8) |
         ((uint32_t)buf[3]);
}

/** Read 4 bytes from buf, as a 32-bit little endian quantity. */
static inline uint32_t read32_le(const uint8_t buf[4])
{
  return ((uint32_t)buf[3] << 24) |
         ((uint32_t)buf[2] << 16) |
         ((uint32_t)buf[1] << 8) |
         ((uint32_t)buf[0]);
}

/** Read 8 bytes from buf, as a 64-bit big endian quantity. */
static inline uint64_t read64_be(const uint8_t buf[8])
{
  uint32_t hi = read32_be(buf),
           lo = read32_be(buf + 4);
  return ((uint64_t)hi) << 32 |
         lo;
}

/** Read 8 bytes from buf, as a 64-bit little endian quantity. */
static inline uint64_t read64_le(const uint8_t buf[8])
{
  uint32_t hi = read32_le(buf + 4),
           lo = read32_le(buf);
  return ((uint64_t)hi) << 32 |
         lo;
}

/** Encode v as a 32-bit big endian quantity into buf. */
static inline void write32_be(uint32_t v, uint8_t buf[4])
{
  *buf++ = (v >> 24) & 0xff;
  *buf++ = (v >> 16) & 0xff;
  *buf++ = (v >> 8) & 0xff;
  *buf   = v & 0xff;
}

/** Encode v as a 32-bit little endian quantity into buf. */
static inline void write32_le(uint32_t v, uint8_t buf[4])
{
  *buf++ = v & 0xff;
  *buf++ = (v >> 8) & 0xff;
  *buf++ = (v >> 16) & 0xff;
  *buf   = (v >> 24) & 0xff;
}

/** Encode v as a 64-bit big endian quantity into buf. */
static inline void write64_be(uint64_t v, uint8_t buf[8])
{
  *buf++ = (v >> 56) & 0xff;
  *buf++ = (v >> 48) & 0xff;
  *buf++ = (v >> 40) & 0xff;
  *buf++ = (v >> 32) & 0xff;
  *buf++ = (v >> 24) & 0xff;
  *buf++ = (v >> 16) & 0xff;
  *buf++ = (v >> 8) & 0xff;
  *buf   = v & 0xff;
}

/** Encode v as a 64-bit little endian quantity into buf. */
static inline void write64_le(uint64_t v, uint8_t buf[8])
{
  *buf++ = v & 0xff;
  *buf++ = (v >> 8) & 0xff;
  *buf++ = (v >> 16) & 0xff;
  *buf++ = (v >> 24) & 0xff;
  *buf++ = (v >> 32) & 0xff;
  *buf++ = (v >> 40) & 0xff;
  *buf++ = (v >> 48) & 0xff;
  *buf   = (v >> 56) & 0xff;
}

/** out = in ^ b8.
 *  out and in may alias. */
static inline void xor_b8(uint8_t *out, const uint8_t *in, uint8_t b8, size_t len)
{
  size_t i;
  for (i = 0; i < len; i++)
    out[i] = in[i] ^ b8;
}

/** out = x ^ y.
 *  out, x and y may alias. */
static inline void xor_bb(uint8_t *out, const uint8_t *x, const uint8_t *y, size_t len)
{
  size_t i;
  for (i = 0; i < len; i++)
    out[i] = x[i] ^ y[i];
}

/* out ^= x
 * out and x may alias. */
static inline void xor_words(uint32_t *out, const uint32_t *x, size_t nwords)
{
  size_t i;
  for (i = 0; i < nwords; i++)
    out[i] ^= x[i];
}

/** Produce 0xffffffff if x == y, zero otherwise, without branching. */
static inline uint32_t mask_u32(uint32_t x, uint32_t y)
{
  uint32_t diff = x ^ y;
  uint32_t diff_is_zero = ~diff & (diff - 1);
  return (uint32_t)(-(int32_t)(diff_is_zero >> 31));
}

/** Product 0xff if x == y, zero otherwise, without branching. */
static inline uint8_t mask_u8(uint32_t x, uint32_t y)
{
  uint32_t diff = x ^ y;
  uint8_t diff_is_zero = ~diff & (diff - 1);
  return - (diff_is_zero >> 7);
}

/** Select the ith entry from the given table of n values, in a side channel-silent
 *  way. */
static inline uint32_t select_u32(uint32_t i, volatile const uint32_t *tab, uint32_t n)
{
  uint32_t r = 0, ii;

  for (ii = 0; ii < n; ii++)
  {
    uint32_t mask = mask_u32(i, ii);
    r = (r & ~mask) | (tab[ii] & mask);
  }

  return r;
}

/** Select the ith entry from the given table of n values, in a side channel-silent
 *  way. */
static inline uint8_t select_u8(uint32_t i, volatile const uint8_t *tab, uint32_t n)
{
  uint8_t r = 0;
  uint32_t ii;

  for (ii = 0; ii < n; ii++)
  {
    uint8_t mask = mask_u8(i, ii);
    r = (r & ~mask) | (tab[ii] & mask);
  }

  return r;
}

/** Select the ath, bth, cth and dth entries from the given table of n values,
 *  placing the results into a, b, c and d. */
static inline void select_u8x4(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d,
                               volatile const uint8_t *tab, uint32_t n)
{
  uint8_t ra = 0,
          rb = 0,
          rc = 0,
          rd = 0;
  uint8_t mask;
  uint32_t i;

  for (i = 0; i < n; i++)
  {
    uint8_t item = tab[i];

    mask = mask_u8(*a, i); ra = (ra & ~mask) | (item & mask);
    mask = mask_u8(*b, i); rb = (rb & ~mask) | (item & mask);
    mask = mask_u8(*c, i); rc = (rc & ~mask) | (item & mask);
    mask = mask_u8(*d, i); rd = (rd & ~mask) | (item & mask);
  }

  *a = ra;
  *b = rb;
  *c = rc;
  *d = rd;
}

/** out ^= if0 or if1, depending on the value of bit. */
static inline void select_xor128(uint32_t out[4],
                                 const uint32_t if0[4],
                                 const uint32_t if1[4],
                                 uint8_t bit)
{
  uint32_t mask1 = mask_u32(bit, 1);
  uint32_t mask0 = ~mask1;

  out[0] ^= (if0[0] & mask0) | (if1[0] & mask1);
  out[1] ^= (if0[1] & mask0) | (if1[1] & mask1);
  out[2] ^= (if0[2] & mask0) | (if1[2] & mask1);
  out[3] ^= (if0[3] & mask0) | (if1[3] & mask1);
}

/** Increments the integer stored at v (of non-zero length len)
 *  with the least significant byte first. */
static inline void incr_le(uint8_t *v, size_t len)
{
  size_t i = 0;
  while (1)
  {
    if (++v[i] != 0)
      return;
    i++;
    if (i == len)
      return;
  }
}

/** Increments the integer stored at v (of non-zero length len)
 *  with the most significant byte last. */
static inline void incr_be(uint8_t *v, size_t len)
{
  len--;
  while (1)
  {
    if (++v[len] != 0)
      return;
    if (len == 0)
      return;
    len--;
  }
}

/** Copies len bytes from in to out, with in shifted left by offset bits
 *  to the right. */
static inline void copy_bytes_unaligned(uint8_t *out, const uint8_t *in, size_t len, uint8_t offset)
{
  uint8_t byte_off = offset / 8;
  uint8_t bit_off = offset & 7;
  uint8_t rmask = (1 << bit_off) - 1;
  uint8_t lmask = ~rmask;
  size_t i;

  for (i = 0; i < len; i++)
  {
    out[i] = (in[i + byte_off] << bit_off) & lmask;
    out[i] |= (in[i + byte_off + 1] >> (8 - bit_off)) & rmask;
  }
}

static inline uint32_t count_trailing_zeroes(uint32_t x)
{
#ifdef _WINDOWS
  uint32_t r = 0;
  _BitScanReverse(&r, x);
  return (31 - r);
#else
  return (uint32_t) __builtin_ctzl(x);
#endif
}

#endif
