diff options
Diffstat (limited to 'comm/third_party/botan/src/lib/utils/donna128.h')
-rw-r--r-- | comm/third_party/botan/src/lib/utils/donna128.h | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/utils/donna128.h b/comm/third_party/botan/src/lib/utils/donna128.h new file mode 100644 index 0000000000..ff571906d8 --- /dev/null +++ b/comm/third_party/botan/src/lib/utils/donna128.h @@ -0,0 +1,143 @@ +/* +* A minimal 128-bit integer type for curve25519-donna +* (C) 2014 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_CURVE25519_DONNA128_H_ +#define BOTAN_CURVE25519_DONNA128_H_ + +#include <botan/mul128.h> + +namespace Botan { + +class donna128 final + { + public: + donna128(uint64_t ll = 0, uint64_t hh = 0) { l = ll; h = hh; } + + donna128(const donna128&) = default; + donna128& operator=(const donna128&) = default; + + friend donna128 operator>>(const donna128& x, size_t shift) + { + donna128 z = x; + if(shift > 0) + { + const uint64_t carry = z.h << (64 - shift); + z.h = (z.h >> shift); + z.l = (z.l >> shift) | carry; + } + return z; + } + + friend donna128 operator<<(const donna128& x, size_t shift) + { + donna128 z = x; + if(shift > 0) + { + const uint64_t carry = z.l >> (64 - shift); + z.l = (z.l << shift); + z.h = (z.h << shift) | carry; + } + return z; + } + + friend uint64_t operator&(const donna128& x, uint64_t mask) + { + return x.l & mask; + } + + uint64_t operator&=(uint64_t mask) + { + h = 0; + l &= mask; + return l; + } + + donna128& operator+=(const donna128& x) + { + l += x.l; + h += x.h; + + const uint64_t carry = (l < x.l); + h += carry; + return *this; + } + + donna128& operator+=(uint64_t x) + { + l += x; + const uint64_t carry = (l < x); + h += carry; + return *this; + } + + uint64_t lo() const { return l; } + uint64_t hi() const { return h; } + private: + uint64_t h = 0, l = 0; + }; + +inline donna128 operator*(const donna128& x, uint64_t y) + { + BOTAN_ARG_CHECK(x.hi() == 0, "High 64 bits of donna128 set to zero during multiply"); + + uint64_t lo = 0, hi = 0; + mul64x64_128(x.lo(), y, &lo, &hi); + return donna128(lo, hi); + } + +inline donna128 operator*(uint64_t y, const donna128& x) + { + return x * y; + } + +inline donna128 operator+(const donna128& x, const donna128& y) + { + donna128 z = x; + z += y; + return z; + } + +inline donna128 operator+(const donna128& x, uint64_t y) + { + donna128 z = x; + z += y; + return z; + } + +inline donna128 operator|(const donna128& x, const donna128& y) + { + return donna128(x.lo() | y.lo(), x.hi() | y.hi()); + } + +inline uint64_t carry_shift(const donna128& a, size_t shift) + { + return (a >> shift).lo(); + } + +inline uint64_t combine_lower(const donna128& a, size_t s1, + const donna128& b, size_t s2) + { + donna128 z = (a >> s1) | (b << s2); + return z.lo(); + } + +#if defined(BOTAN_TARGET_HAS_NATIVE_UINT128) +inline uint64_t carry_shift(const uint128_t a, size_t shift) + { + return static_cast<uint64_t>(a >> shift); + } + +inline uint64_t combine_lower(const uint128_t a, size_t s1, + const uint128_t b, size_t s2) + { + return static_cast<uint64_t>((a >> s1) | (b << s2)); + } +#endif + +} + +#endif |