blob: 89fe7d05d4be54f01a8d783ae915d2e6383feadc [file] [log] [blame]
#ifndef BEDROCK_UNVERIFIED_PLATFORM_INC_H_
#define BEDROCK_UNVERIFIED_PLATFORM_INC_H_
// This file is a manually maintained and audited replacement for
// bedrock_polyfill_platform.c.inc with tests in bedrock_platform_test.cc
#include "../../crypto/internal.h"
#if defined(OPENSSL_64_BIT)
#define BR_WORD_MAX UINT64_MAX
typedef uint64_t br_word_t;
typedef int64_t br_signed_t;
#elif defined(OPENSSL_32_BIT)
#define BR_WORD_MAX UINT32_MAX
typedef uint32_t br_word_t;
typedef int32_t br_signed_t;
#else
#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT"
#endif
static_assert(sizeof(br_word_t) == sizeof(crypto_word_t));
// Scalar memory operations
#include "../../third_party/fiat/bedrock_unverified_bareminimum.c.inc"
// Bulk memory operations
static inline void br_memcpy(br_word_t d, br_word_t s, br_word_t n) {
OPENSSL_memcpy((void *)d, (const void *)s, n);
}
static inline void br_memset(br_word_t d, br_word_t v, br_word_t n) {
OPENSSL_memset((void *)d, v, n);
}
static inline void br_memcxor(uintptr_t d, uintptr_t s, uintptr_t n, uintptr_t mask) {
constant_time_conditional_memxor((void*)d, (void*)s, n, mask);
}
// CPU Arithmetic
static inline br_word_t br_full_add(br_word_t x, br_word_t y, br_word_t carry,
br_word_t *_sum) {
br_word_t carry_out = 0;
static_assert(sizeof(br_word_t) == sizeof(crypto_word_t));
*_sum = CRYPTO_addc_w(x, y, carry, &carry_out);
return carry_out;
}
static inline br_word_t br_full_sub(br_word_t x, br_word_t y, br_word_t borrow,
br_word_t *_diff) {
br_word_t borrow_out = 0;
static_assert(sizeof(br_word_t) == sizeof(crypto_word_t));
*_diff = CRYPTO_subc_w(x, y, borrow, &borrow_out);
return borrow_out;
}
static inline br_word_t br_full_mul(br_word_t a, br_word_t b, br_word_t *_low) {
#if BR_WORD_MAX == UINT32_MAX
uint64_t r = (uint64_t)a * b;
*_low = r;
return r >> 32;
#elif defined(BORINGSSL_HAS_UINT128)
uint128_t r = (uint128_t)a * b;
*_low = r;
return r >> 64;
#elif defined(_M_X64)
uint64_t hi;
*_low = _umul128(a, b, &hi);
return hi;
#elif defined(_M_ARM64)
*_low = a * b;
return __umulh(a, b);
#else
#error "need 64 x 64 -> 128 multiplication"
#endif
}
// Constant-time computations
static inline br_word_t br_value_barrier(br_word_t a) {
static_assert(sizeof(br_word_t) == sizeof(crypto_word_t));
return value_barrier_w(a);
}
static inline br_word_t br_declassify(br_word_t a) {
static_assert(sizeof(br_word_t) == sizeof(crypto_word_t));
return constant_time_declassify_w(a);
}
static inline br_word_t br_broadcast_negative(br_word_t x) {
return br_value_barrier((br_signed_t)x >> (sizeof(br_word_t) * 8 - 1));
}
static inline br_word_t br_broadcast_nonzero(br_word_t x) {
return br_broadcast_negative(x | (0u - x));
}
static inline br_word_t br_cmov(br_word_t c, br_word_t vnz, br_word_t vz) {
#if !defined(OPENSSL_NO_ASM) && (defined(__GNUC__) || defined(__clang__)) && \
defined(__x86_64__)
__asm__(
"testq %[c], %[c]\n"
"cmovzq %[vz], %[vnz]"
: [vnz] "+r"(vnz)
: [vz] "r"(vz), [c] "r"(c)
: "cc");
return vnz;
#elif !defined(OPENSSL_NO_ASM) && (defined(__GNUC__) || defined(__clang__)) && \
defined(__i386__)
__asm__(
"testl %[c], %[c]\n" // test%z[c] gives "invalid operand" on clang 16.0.6
"cmovzl %[vz], %[vnz]"
: [vnz] "+r"(vnz)
: [vz] "r"(vz), [c] "r"(c)
: "cc");
return vnz;
#else
br_word_t m = br_broadcast_nonzero(c);
return (m & vnz) | (~m & vz);
#endif
}
#endif // BEDROCK_UNVERIFIED_PLATFORM_INC_H_