1#ifndef SECP256K1_CT_OPS_HPP
2#define SECP256K1_CT_OPS_HPP
47#if defined(SECP256K1_CT_VALGRIND) && SECP256K1_CT_VALGRIND
48 #include <valgrind/memcheck.h>
49 #define SECP256K1_CLASSIFY(ptr, len) VALGRIND_MAKE_MEM_UNDEFINED((ptr), (len))
50 #define SECP256K1_DECLASSIFY(ptr, len) VALGRIND_MAKE_MEM_DEFINED((ptr), (len))
52 #define SECP256K1_CLASSIFY(ptr, len) ((void)(ptr), (void)(len))
53 #define SECP256K1_DECLASSIFY(ptr, len) ((void)(ptr), (void)(len))
56#if defined(__GNUC__) || defined(__clang__)
57 #define SECP256K1_CT_NO_STACK_PROTECTOR __attribute__((no_stack_protector))
59 #define SECP256K1_CT_NO_STACK_PROTECTOR
68#if defined(__GNUC__) || defined(__clang__)
78 asm volatile(
"" :
"+r"(v));
81 asm volatile(
"" :
"+r"(v));
86 asm volatile(
"" :
"+r"(v) : :
"memory");
89 asm volatile(
"" :
"+r"(v) : :
"memory");
95 volatile std::uint64_t sink = v;
99 volatile std::uint32_t sink = v;
108#if defined(__riscv) && (__riscv_xlen == 64)
118 :
"=r"(mask) :
"r"(v));
123 std::uint64_t nv = 0ULL - v;
125 auto mask =
static_cast<std::uint64_t
>(
126 -
static_cast<std::int64_t
>((~(v | nv)) >> 63));
134 return ~is_zero_mask(v);
138inline std::uint64_t
eq_mask(std::uint64_t a, std::uint64_t b)
noexcept {
144 auto v =
static_cast<std::uint64_t
>(flag);
146 std::uint64_t mask = 0ULL - v;
153inline std::uint64_t
lt_mask(std::uint64_t a, std::uint64_t b)
noexcept {
156 std::uint64_t
const diff = a - b;
159 std::uint64_t borrow = (a ^ ((a ^ b) | (diff ^ a))) >> 63;
161 return 0ULL - borrow;
167inline void cmov64(std::uint64_t* dst,
const std::uint64_t* src,
168 std::uint64_t mask)
noexcept {
170 *dst ^= (*dst ^ *src) & mask;
174inline void cmov256(std::uint64_t dst[4],
const std::uint64_t src[4],
175 std::uint64_t mask)
noexcept {
176 dst[0] ^= (dst[0] ^ src[0]) & mask;
177 dst[1] ^= (dst[1] ^ src[1]) & mask;
178 dst[2] ^= (dst[2] ^ src[2]) & mask;
179 dst[3] ^= (dst[3] ^ src[3]) & mask;
185inline void cswap256(std::uint64_t a[4], std::uint64_t b[4],
186 std::uint64_t mask)
noexcept {
187 std::uint64_t
const diff0 = (a[0] ^ b[0]) & mask;
191 std::uint64_t
const diff1 = (a[1] ^ b[1]) & mask;
195 std::uint64_t
const diff2 = (a[2] ^ b[2]) & mask;
199 std::uint64_t
const diff3 = (a[3] ^ b[3]) & mask;
207inline std::uint64_t
ct_select(std::uint64_t a, std::uint64_t b,
208 std::uint64_t mask)
noexcept {
209 return (a & mask) | (b & ~mask);
218inline void ct_lookup(
const void* table, std::size_t count,
219 std::size_t stride, std::size_t index,
220 void* out)
noexcept {
222 auto* dst =
static_cast<std::uint8_t*
>(out);
223 for (std::size_t b = 0; b < stride; ++b) dst[b] = 0;
225 const auto* src =
static_cast<const std::uint8_t*
>(table);
226 for (std::size_t i = 0; i < count; ++i) {
227 std::uint64_t
const mask =
eq_mask(
static_cast<std::uint64_t
>(i),
228 static_cast<std::uint64_t
>(index));
229 auto mask8 =
static_cast<std::uint8_t
>(mask & 0xFF);
230 for (std::size_t b = 0; b < stride; ++b) {
231 dst[b] |= src[i * stride + b] & mask8;
238 std::size_t index, std::uint64_t out[4])
noexcept {
239 out[0] = out[1] = out[2] = out[3] = 0;
240 for (std::size_t i = 0; i < count; ++i) {
241 std::uint64_t
const mask =
eq_mask(
static_cast<std::uint64_t
>(i),
242 static_cast<std::uint64_t
>(index));
243 out[0] |= table[i][0] & mask;
244 out[1] |= table[i][1] & mask;
245 out[2] |= table[i][2] & mask;
246 out[3] |= table[i][3] & mask;
252#undef SECP256K1_CT_NO_STACK_PROTECTOR
std::uint64_t lt_mask(std::uint64_t a, std::uint64_t b) noexcept
void cswap256(std::uint64_t a[4], std::uint64_t b[4], std::uint64_t mask) noexcept
void cmov64(std::uint64_t *dst, const std::uint64_t *src, std::uint64_t mask) noexcept
std::uint64_t ct_select(std::uint64_t a, std::uint64_t b, std::uint64_t mask) noexcept
std::uint64_t is_nonzero_mask(std::uint64_t v) noexcept
void cmov256(std::uint64_t dst[4], const std::uint64_t src[4], std::uint64_t mask) noexcept
void value_barrier(std::uint64_t &v) noexcept
SECP256K1_CT_NO_STACK_PROTECTOR std::uint64_t bool_to_mask(bool flag) noexcept
std::uint64_t eq_mask(std::uint64_t a, std::uint64_t b) noexcept
SECP256K1_CT_NO_STACK_PROTECTOR std::uint64_t is_zero_mask(std::uint64_t v) noexcept
void ct_lookup(const void *table, std::size_t count, std::size_t stride, std::size_t index, void *out) noexcept
void ct_lookup_256(const std::uint64_t table[][4], std::size_t count, std::size_t index, std::uint64_t out[4]) noexcept
#define SECP256K1_CT_NO_STACK_PROTECTOR