Revision control
Copy as Markdown
Other Tools
/*
* 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