Botan
1.11.15
|
00001 /* 00002 * A minimal 128-bit integer type for curve25519-donna 00003 * (C) 2014 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #ifndef BOTAN_CURVE25519_DONNA128_H__ 00009 #define BOTAN_CURVE25519_DONNA128_H__ 00010 00011 #include <botan/mul128.h> 00012 00013 namespace Botan { 00014 00015 class donna128 00016 { 00017 public: 00018 donna128(u64bit ll = 0, u64bit hh = 0) { l = ll; h = hh; } 00019 00020 donna128(const donna128&) = default; 00021 donna128& operator=(const donna128&) = default; 00022 00023 friend donna128 operator>>(const donna128& x, size_t shift) 00024 { 00025 donna128 z = x; 00026 const u64bit carry = z.h << (64 - shift); 00027 z.h = (z.h >> shift); 00028 z.l = (z.l >> shift) | carry; 00029 return z; 00030 } 00031 00032 friend donna128 operator<<(const donna128& x, size_t shift) 00033 { 00034 donna128 z = x; 00035 const u64bit carry = z.l >> (64 - shift); 00036 z.l = (z.l << shift); 00037 z.h = (z.h << shift) | carry; 00038 return z; 00039 } 00040 00041 friend u64bit operator&(const donna128& x, u64bit mask) 00042 { 00043 return x.l & mask; 00044 } 00045 00046 u64bit operator&=(u64bit mask) 00047 { 00048 h = 0; 00049 l &= mask; 00050 return l; 00051 } 00052 00053 donna128& operator+=(const donna128& x) 00054 { 00055 l += x.l; 00056 h += (l < x.l); 00057 h += x.h; 00058 return *this; 00059 } 00060 00061 donna128& operator+=(u64bit x) 00062 { 00063 l += x; 00064 h += (l < x); 00065 return *this; 00066 } 00067 00068 u64bit lo() const { return l; } 00069 u64bit hi() const { return h; } 00070 private: 00071 u64bit h = 0, l = 0; 00072 }; 00073 00074 inline donna128 operator*(const donna128& x, u64bit y) 00075 { 00076 BOTAN_ASSERT(x.hi() == 0, "High 64 bits of donna128 set to zero during multiply"); 00077 00078 u64bit lo = 0, hi = 0; 00079 mul64x64_128(x.lo(), y, &lo, &hi); 00080 return donna128(lo, hi); 00081 } 00082 00083 inline donna128 operator+(const donna128& x, const donna128& y) 00084 { 00085 donna128 z = x; 00086 z += y; 00087 return z; 00088 } 00089 00090 inline donna128 operator+(const donna128& x, u64bit y) 00091 { 00092 donna128 z = x; 00093 z += y; 00094 return z; 00095 } 00096 00097 inline donna128 operator|(const donna128& x, const donna128& y) 00098 { 00099 return donna128(x.lo() | y.lo(), x.hi() | y.hi()); 00100 } 00101 00102 inline u64bit carry_shift(const donna128& a, size_t shift) 00103 { 00104 return (a >> shift).lo(); 00105 } 00106 00107 inline u64bit combine_lower(const donna128 a, size_t s1, 00108 const donna128 b, size_t s2) 00109 { 00110 donna128 z = (a >> s1) | (b << s2); 00111 return z.lo(); 00112 } 00113 00114 #if defined(BOTAN_TARGET_HAS_NATIVE_UINT128) 00115 inline u64bit carry_shift(const uint128_t a, size_t shift) 00116 { 00117 return static_cast<u64bit>(a >> shift); 00118 } 00119 00120 inline u64bit combine_lower(const uint128_t a, size_t s1, 00121 const uint128_t b, size_t s2) 00122 { 00123 return static_cast<u64bit>((a >> s1) | (b << s2)); 00124 } 00125 #endif 00126 00127 } 00128 00129 #endif