1 /** 2 * A minimal 128-bit integer type for curve25519-donna 3 * 4 * (C) 2014 Jack Lloyd 5 * (C) 2014-2015 Etienne Cimon 6 * 7 * License: 8 * Botan is released under the Simplified BSD License (see LICENSE.md) 9 */ 10 module botan.utils.donna128; 11 12 import botan.utils.mul128; 13 14 struct donna128 15 { 16 public: 17 void opAssign(donna128 other) { 18 this.l = other.l; 19 this.h = other.h; 20 } 21 22 void opAssign(in ulong other) { 23 this.l = other; 24 } 25 26 donna128 opBinary(string op)(size_t shift) const 27 if (op == ">>") 28 { 29 donna128 z = this; 30 const ulong carry = z.h << (64 - shift); 31 z.h = (z.h >> shift); 32 z.l = (z.l >> shift) | carry; 33 return z; 34 } 35 36 donna128 opBinary(string op)(size_t shift) const 37 if (op == "<<") 38 { 39 donna128 z = donna128(l, h); 40 const ulong carry = z.l >> (64 - shift); 41 z.l = (z.l << shift); 42 z.h = (z.h << shift) | carry; 43 return z; 44 } 45 46 ulong opBinary(string op)(ulong mask) const 47 if (op == "&") 48 { 49 return l & mask; 50 } 51 52 ulong opOpAssign(string op)(ulong mask) 53 if (op == "&") 54 { 55 h = 0; 56 l &= mask; 57 return l; 58 } 59 60 donna128 opOpAssign(string op)(auto const ref donna128 x) 61 if (op == "+") 62 { 63 l += x.l; 64 h += (l < x.l); 65 h += x.h; 66 return donna128(l, h); 67 } 68 69 donna128 opOpAssign(string op)(ulong x) 70 if (op == "+") 71 { 72 l += x; 73 h += (l < x); 74 return donna128(l, h); 75 } 76 77 donna128 opBinary(string op)(ulong y) 78 if (op == "*") 79 { 80 assert(hi() == 0, "High 64 bits of donna128 set to zero during multiply"); 81 82 ulong[2] lohi; 83 mul64x64_128(this.lo(), y, lohi); 84 return donna128(lohi[0], lohi[1]); 85 } 86 87 donna128 opBinary(string op)(auto const ref donna128 y) const 88 if (op == "+") 89 { 90 donna128 z = donna128(l, h); 91 z += y; 92 return z; 93 } 94 95 donna128 opBinary(string op)(ulong y) const 96 if (op == "+") 97 { 98 donna128 z = donna128(l, h); 99 z += y; 100 return z; 101 } 102 103 donna128 opBinary(string op)(auto const ref donna128 y) const 104 if (op == "|") 105 { 106 return donna128(this.lo() | y.lo(), this.hi() | y.hi()); 107 } 108 109 ulong lo() const { return l;} 110 ulong hi() const { return h;} 111 ulong l; 112 ulong h; 113 } 114 115 116 ulong carry_shift(const donna128 a, size_t shift) 117 { 118 return (a >> shift).lo(); 119 } 120 121 ulong combine_lower(in donna128 a, size_t s1, 122 in donna128 b, size_t s2) 123 { 124 donna128 z = (a >> s1) | (b << s2); 125 return z.lo(); 126 }