#pragma once
#include <string.h>
#include "types.h"
#define ROTR64(x, s) (((x) >> (s)) | (x) << (64 - (s)))
#if defined(__GNUC__) && __GNUC__ >= 2
_INLINE_ uint64_t bswap_64(uint64_t x) { return __builtin_bswap64(x); }
#else
# define ROTR16(x, s) (((x) >> (s)) | (x) << (16 - (s)))
_INLINE_ uint32_t bswap_32(uint32_t x)
{
x = ROTR16(x, 16);
x = ((x & UINT32_C(0xff00ff00)) >> 8) | ((x & UINT32_C(0x00ff00ff)) << 8);
return x;
}
_INLINE_ uint64_t bswap_64(uint64_t x)
{
return bswap_32(x >> 32) | (((uint64_t)bswap_32(x)) << 32);
}
#endif
uint64_t r_bits_vector_weight(IN const r_t *in);
#if(defined(__GNUC__) || defined(__clang__))
# define VALUE_BARRIER(name, type) \
_INLINE_ type name##_barrier(type a) \
{ \
__asm__("" : "+r"(a) : ); \
return a; \
}
#else
# define VALUE_BARRIER(name, type) \
_INLINE_ type name##_barrier(type a) { return a; }
#endif
VALUE_BARRIER(u8, uint8_t)
VALUE_BARRIER(u32, uint32_t)
VALUE_BARRIER(u64, uint64_t)
_INLINE_ uint32_t secure_cmp(IN const uint8_t *a,
IN const uint8_t *b,
IN const uint32_t size)
{
volatile uint8_t res = 0;
for(uint32_t i = 0; i < size; ++i) {
res |= (a[i] ^ b[i]);
}
return (0 == res);
}
_INLINE_ uint32_t secure_cmp32(IN const uint32_t v1, IN const uint32_t v2)
{
#if defined(__aarch64__)
uint32_t res;
__asm__ __volatile__("cmp %w[V1], %w[V2]; \n "
"cset %w[RES], EQ; \n"
: [RES] "=r"(res)
: [V1] "r"(v1), [V2] "r"(v2)
: "cc" );
return res;
#elif defined(__x86_64__) || defined(__i386__)
uint32_t res;
__asm__ __volatile__("xor %%edx, %%edx; \n"
"cmp %1, %2; \n "
"sete %%dl; \n"
"mov %%edx, %0; \n"
: "=r"(res)
: "r"(v1), "r"(v2)
: "rdx");
return res;
#else
return (v1 == v2 ? 1 : 0);
#endif
}
_INLINE_ uint32_t secure_l32_mask(IN const uint32_t v1, IN const uint32_t v2)
{
#if defined(__aarch64__)
uint32_t res;
__asm__ __volatile__("cmp %w[V2], %w[V1]; \n "
"cset %w[RES], HI; \n"
: [RES] "=r"(res)
: [V1] "r"(v1), [V2] "r"(v2)
: "cc" );
return (res - 1);
#elif defined(__x86_64__) || defined(__i386__)
uint32_t res;
__asm__ __volatile__("xor %%edx, %%edx; \n"
"cmp %1, %2; \n "
"setl %%dl; \n"
"dec %%edx; \n"
"mov %%edx, %0; \n"
: "=r"(res)
: "r"(v2), "r"(v1)
: "rdx");
return res;
#else
return ~((uint32_t)(((uint64_t)v1 - (uint64_t)v2) >> 32));
#endif
}
_INLINE_ uint64_t secure_cmpeq64_mask(IN const uint64_t v1, IN const uint64_t v2) {
return -(1 - ((uint64_t)((v1-v2) | (v2-v1)) >> 63));
}
_INLINE_ void *bike_memcpy(void *dst, const void *src, size_t byte_len)
{
if(byte_len == 0) {
return dst;
}
return memcpy(dst, src, byte_len);
}
_INLINE_ void *bike_memset(void *dst, const int ch, size_t byte_len)
{
if(byte_len == 0) {
return dst;
}
return memset(dst, ch, byte_len);
}
#if defined(VERBOSE)
void print_LE(IN const uint64_t *in, IN uint32_t bits_num);
void print_BE(IN const uint64_t *in, IN uint32_t bits_num);
# if defined(PRINT_IN_BE)
# define print(name, in, bits_num) \
do { \
DMSG(name); \
print_BE(in, bits_num); \
} while(0)
# else
# define print(name, in, bits_num) \
do { \
DMSG(name); \
print_LE(in, bits_num); \
} while(0)
# endif
#else
# define print(name, in, bits_num)
#endif