/* * 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 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_ASSERT(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+(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(a >> shift); } inline uint64_t combine_lower(const uint128_t a, size_t s1, const uint128_t b, size_t s2) { return static_cast((a >> s1) | (b << s2)); } #endif } #endif