aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/utils/ct_utils.h
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2018-09-07 17:16:02 -0400
committerJack Lloyd <[email protected]>2018-09-07 17:23:16 -0400
commit63cbaf52e414b2ac138d1c95143a3238741df21c (patch)
tree266bb20924a2da9d7497e8d25f3ec71de8bed19a /src/lib/utils/ct_utils.h
parent643a4041bedc18b70dde1fc257c54d6415fd352b (diff)
Optimize CT::is_zero, CT::expand_mask, CT::expand_top_bit
Diffstat (limited to 'src/lib/utils/ct_utils.h')
-rw-r--r--src/lib/utils/ct_utils.h41
1 files changed, 20 insertions, 21 deletions
diff --git a/src/lib/utils/ct_utils.h b/src/lib/utils/ct_utils.h
index 013267874..4fd06ec3d 100644
--- a/src/lib/utils/ct_utils.h
+++ b/src/lib/utils/ct_utils.h
@@ -15,6 +15,7 @@
#define BOTAN_TIMING_ATTACK_CM_H_
#include <botan/secmem.h>
+#include <type_traits>
#include <vector>
#if defined(BOTAN_HAS_VALGRIND)
@@ -74,6 +75,22 @@ inline void unpoison(T& p)
#endif
}
+/* Mask generation */
+
+template<typename T>
+inline T expand_top_bit(T a)
+ {
+ static_assert(std::is_unsigned<T>::value, "unsigned integer type required");
+ return static_cast<T>(0) - (a >> (sizeof(T)*8-1));
+ }
+
+template<typename T>
+inline T is_zero(T x)
+ {
+ static_assert(std::is_unsigned<T>::value, "unsigned integer type required");
+ return expand_top_bit<T>(~x & (x - 1));
+ }
+
/*
* T should be an unsigned machine integer type
* Expand to a mask used for other operations
@@ -85,26 +102,14 @@ inline void unpoison(T& p)
template<typename T>
inline T expand_mask(T x)
{
- T r = x;
- // First fold r down to a single bit
- for(size_t i = 1; i != sizeof(T)*8; i *= 2)
- {
- r = r | static_cast<T>(r >> i);
- }
- r &= 1;
- r = static_cast<T>(~(r - 1));
- return r;
- }
-
-template<typename T>
-inline T expand_top_bit(T a)
- {
- return expand_mask<T>(a >> (sizeof(T)*8-1));
+ static_assert(std::is_unsigned<T>::value, "unsigned integer type required");
+ return ~is_zero(x);
}
template<typename T>
inline T select(T mask, T from0, T from1)
{
+ static_assert(std::is_unsigned<T>::value, "unsigned integer type required");
return static_cast<T>((from0 & mask) | (from1 & ~mask));
}
@@ -127,12 +132,6 @@ inline ValT val_or_zero(PredT pred_val, ValT val)
}
template<typename T>
-inline T is_zero(T x)
- {
- return static_cast<T>(~expand_mask(x));
- }
-
-template<typename T>
inline T is_equal(T x, T y)
{
return is_zero<T>(x ^ y);