Implement CRYPTO_addc_* and CRYPTO_subc_* in C++ more straightforwardly We don't need partial specialization. Plain overflows work just fine. We probably can just use overloads and remove the type-suffixed functions and everything, here and in our constant-time functions and whatnot, but I've left that alone for now. Change-Id: I701f40edac7457a1a0e3702644b3f7ba7bd3daea Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/73747 Auto-Submit: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com> Commit-Queue: Adam Langley <agl@google.com>
diff --git a/crypto/internal.h b/crypto/internal.h index 6821618..8c1900b 100644 --- a/crypto/internal.h +++ b/crypto/internal.h
@@ -1558,49 +1558,33 @@ // bit. |carry| must be zero or one. #if OPENSSL_HAS_BUILTIN(__builtin_addc) -template <typename T> -struct CRYPTO_addc_impl { - static_assert(sizeof(T) == 0, "Unsupported type for addc operation"); -}; +inline unsigned int CRYPTO_addc_impl(unsigned int x, unsigned int y, + unsigned int carry, + unsigned int *out_carry) { + return __builtin_addc(x, y, carry, out_carry); +} -template <> -struct CRYPTO_addc_impl<unsigned int> { - static unsigned int add(unsigned int x, unsigned int y, unsigned int carry, - unsigned int *out_carry) { - return __builtin_addc(x, y, carry, out_carry); - } -}; +inline unsigned long CRYPTO_addc_impl(unsigned long x, unsigned long y, + unsigned long carry, + unsigned long *out_carry) { + return __builtin_addcl(x, y, carry, out_carry); +} -template <> -struct CRYPTO_addc_impl<unsigned long> { - static unsigned long add(unsigned long x, unsigned long y, - unsigned long carry, unsigned long *out_carry) { - return __builtin_addcl(x, y, carry, out_carry); - } -}; - -template <> -struct CRYPTO_addc_impl<unsigned long long> { - static unsigned long long add(unsigned long long x, unsigned long long y, - unsigned long long carry, - unsigned long long *out_carry) { - return __builtin_addcll(x, y, carry, out_carry); - } -}; - -template <typename T> -inline T CRYPTO_addc(T x, T y, T carry, T *out_carry) { - return CRYPTO_addc_impl<T>::add(x, y, carry, out_carry); +inline unsigned long long CRYPTO_addc_impl(unsigned long long x, + unsigned long long y, + unsigned long long carry, + unsigned long long *out_carry) { + return __builtin_addcll(x, y, carry, out_carry); } inline uint32_t CRYPTO_addc_u32(uint32_t x, uint32_t y, uint32_t carry, uint32_t *out_carry) { - return CRYPTO_addc(x, y, carry, out_carry); + return CRYPTO_addc_impl(x, y, carry, out_carry); } inline uint64_t CRYPTO_addc_u64(uint64_t x, uint64_t y, uint64_t carry, uint64_t *out_carry) { - return CRYPTO_addc(x, y, carry, out_carry); + return CRYPTO_addc_impl(x, y, carry, out_carry); } #else @@ -1638,49 +1622,33 @@ // bit. |borrow| must be zero or one. #if OPENSSL_HAS_BUILTIN(__builtin_subc) -template <typename T> -struct CRYPTO_subc_impl { - static_assert(sizeof(T) == 0, "Unsupported type for subc operation"); -}; +inline unsigned int CRYPTO_subc_impl(unsigned int x, unsigned int y, + unsigned int borrow, + unsigned int *out_borrow) { + return __builtin_subc(x, y, borrow, out_borrow); +} -template <> -struct CRYPTO_subc_impl<unsigned int> { - static unsigned int sub(unsigned int x, unsigned int y, unsigned int borrow, - unsigned int *out_borrow) { - return __builtin_subc(x, y, borrow, out_borrow); - } -}; +inline unsigned long CRYPTO_subc_impl(unsigned long x, unsigned long y, + unsigned long borrow, + unsigned long *out_borrow) { + return __builtin_subcl(x, y, borrow, out_borrow); +} -template <> -struct CRYPTO_subc_impl<unsigned long> { - static unsigned long sub(unsigned long x, unsigned long y, - unsigned long borrow, unsigned long *out_borrow) { - return __builtin_subcl(x, y, borrow, out_borrow); - } -}; - -template <> -struct CRYPTO_subc_impl<unsigned long long> { - static unsigned long long sub(unsigned long long x, unsigned long long y, - unsigned long long borrow, - unsigned long long *out_borrow) { - return __builtin_subcll(x, y, borrow, out_borrow); - } -}; - -template <typename T> -inline T CRYPTO_subc(T x, T y, T borrow, T *out_borrow) { - return CRYPTO_subc_impl<T>::sub(x, y, borrow, out_borrow); +inline unsigned long long CRYPTO_subc_impl(unsigned long long x, + unsigned long long y, + unsigned long long borrow, + unsigned long long *out_borrow) { + return __builtin_subcll(x, y, borrow, out_borrow); } inline uint32_t CRYPTO_subc_u32(uint32_t x, uint32_t y, uint32_t borrow, uint32_t *out_borrow) { - return CRYPTO_subc(x, y, borrow, out_borrow); + return CRYPTO_subc_impl(x, y, borrow, out_borrow); } inline uint64_t CRYPTO_subc_u64(uint64_t x, uint64_t y, uint64_t borrow, uint64_t *out_borrow) { - return CRYPTO_subc(x, y, borrow, out_borrow); + return CRYPTO_subc_impl(x, y, borrow, out_borrow); } #else