github.com/cloudflare/circl@v1.5.0/dh/csidh/fp511_generic.go (about) 1 package csidh 2 3 import "math/bits" 4 5 // mul576 implements schoolbook multiplication of 6 // 64x512-bit integer. Returns result modulo 2^512. 7 // r = m1*m2. 8 func mul512Generic(r, m1 *fp, m2 uint64) { 9 var c, h, l uint64 10 11 c, r[0] = bits.Mul64(m2, m1[0]) 12 13 h, l = bits.Mul64(m2, m1[1]) 14 r[1], c = bits.Add64(l, c, 0) 15 c = h + c 16 17 h, l = bits.Mul64(m2, m1[2]) 18 r[2], c = bits.Add64(l, c, 0) 19 c = h + c 20 21 h, l = bits.Mul64(m2, m1[3]) 22 r[3], c = bits.Add64(l, c, 0) 23 c = h + c 24 25 h, l = bits.Mul64(m2, m1[4]) 26 r[4], c = bits.Add64(l, c, 0) 27 c = h + c 28 29 h, l = bits.Mul64(m2, m1[5]) 30 r[5], c = bits.Add64(l, c, 0) 31 c = h + c 32 33 h, l = bits.Mul64(m2, m1[6]) 34 r[6], c = bits.Add64(l, c, 0) 35 c = h + c 36 37 _, l = bits.Mul64(m2, m1[7]) 38 r[7], _ = bits.Add64(l, c, 0) 39 } 40 41 // mul576 implements schoolbook multiplication of 42 // 64x512-bit integer. Returns 576-bit result of 43 // multiplication. 44 // r = m1*m2. 45 func mul576Generic(r *[9]uint64, m1 *fp, m2 uint64) { 46 var c, h, l uint64 47 48 c, r[0] = bits.Mul64(m2, m1[0]) 49 50 h, l = bits.Mul64(m2, m1[1]) 51 r[1], c = bits.Add64(l, c, 0) 52 c = h + c 53 54 h, l = bits.Mul64(m2, m1[2]) 55 r[2], c = bits.Add64(l, c, 0) 56 c = h + c 57 58 h, l = bits.Mul64(m2, m1[3]) 59 r[3], c = bits.Add64(l, c, 0) 60 c = h + c 61 62 h, l = bits.Mul64(m2, m1[4]) 63 r[4], c = bits.Add64(l, c, 0) 64 c = h + c 65 66 h, l = bits.Mul64(m2, m1[5]) 67 r[5], c = bits.Add64(l, c, 0) 68 c = h + c 69 70 h, l = bits.Mul64(m2, m1[6]) 71 r[6], c = bits.Add64(l, c, 0) 72 c = h + c 73 74 h, l = bits.Mul64(m2, m1[7]) 75 r[7], c = bits.Add64(l, c, 0) 76 r[8], c = bits.Add64(h, c, 0) 77 r[8] += c 78 } 79 80 // cswap512 implements constant time swap operation. 81 // If choice = 0, leave x,y unchanged. If choice = 1, set x,y = y,x. 82 // If choice is neither 0 nor 1 then behaviour is undefined. 83 func cswap512Generic(x, y *fp, choice uint8) { 84 var tmp uint64 85 mask64 := 0 - uint64(choice) 86 87 for i := 0; i < numWords; i++ { 88 tmp = mask64 & (x[i] ^ y[i]) 89 x[i] = tmp ^ x[i] 90 y[i] = tmp ^ y[i] 91 } 92 } 93 94 // mulRdc performs montgomery multiplication r = x * y mod P. 95 // Returned result r is already reduced and in Montgomery domain. 96 func mulRdcGeneric(r, x, y *fp) { 97 var t fp 98 var c uint64 99 100 mulGeneric(r, x, y) 101 102 // if p <= r < 2p then r = r-p 103 t[0], c = bits.Sub64(r[0], p[0], 0) 104 t[1], c = bits.Sub64(r[1], p[1], c) 105 t[2], c = bits.Sub64(r[2], p[2], c) 106 t[3], c = bits.Sub64(r[3], p[3], c) 107 t[4], c = bits.Sub64(r[4], p[4], c) 108 t[5], c = bits.Sub64(r[5], p[5], c) 109 t[6], c = bits.Sub64(r[6], p[6], c) 110 t[7], c = bits.Sub64(r[7], p[7], c) 111 112 w := 0 - c 113 r[0] = ctPick64(w, r[0], t[0]) 114 r[1] = ctPick64(w, r[1], t[1]) 115 r[2] = ctPick64(w, r[2], t[2]) 116 r[3] = ctPick64(w, r[3], t[3]) 117 r[4] = ctPick64(w, r[4], t[4]) 118 r[5] = ctPick64(w, r[5], t[5]) 119 r[6] = ctPick64(w, r[6], t[6]) 120 r[7] = ctPick64(w, r[7], t[7]) 121 } 122 123 func mulGeneric(r, x, y *fp) { 124 var s fp // keeps intermediate results 125 var t1, t2 [9]uint64 126 var c, q uint64 127 128 for i := 0; i < numWords-1; i++ { 129 q = ((x[i] * y[0]) + s[0]) * pNegInv[0] 130 mul576Generic(&t1, &p, q) 131 mul576Generic(&t2, y, x[i]) 132 133 // x[i]*y + q_i*p 134 t1[0], c = bits.Add64(t1[0], t2[0], 0) 135 t1[1], c = bits.Add64(t1[1], t2[1], c) 136 t1[2], c = bits.Add64(t1[2], t2[2], c) 137 t1[3], c = bits.Add64(t1[3], t2[3], c) 138 t1[4], c = bits.Add64(t1[4], t2[4], c) 139 t1[5], c = bits.Add64(t1[5], t2[5], c) 140 t1[6], c = bits.Add64(t1[6], t2[6], c) 141 t1[7], c = bits.Add64(t1[7], t2[7], c) 142 t1[8], _ = bits.Add64(t1[8], t2[8], c) 143 144 // s = (s + x[i]*y + q_i * p) / R 145 _, c = bits.Add64(t1[0], s[0], 0) 146 s[0], c = bits.Add64(t1[1], s[1], c) 147 s[1], c = bits.Add64(t1[2], s[2], c) 148 s[2], c = bits.Add64(t1[3], s[3], c) 149 s[3], c = bits.Add64(t1[4], s[4], c) 150 s[4], c = bits.Add64(t1[5], s[5], c) 151 s[5], c = bits.Add64(t1[6], s[6], c) 152 s[6], c = bits.Add64(t1[7], s[7], c) 153 s[7], _ = bits.Add64(t1[8], 0, c) 154 } 155 156 // last iteration stores result in r 157 q = ((x[numWords-1] * y[0]) + s[0]) * pNegInv[0] 158 mul576Generic(&t1, &p, q) 159 mul576Generic(&t2, y, x[numWords-1]) 160 161 t1[0], c = bits.Add64(t1[0], t2[0], c) 162 t1[1], c = bits.Add64(t1[1], t2[1], c) 163 t1[2], c = bits.Add64(t1[2], t2[2], c) 164 t1[3], c = bits.Add64(t1[3], t2[3], c) 165 t1[4], c = bits.Add64(t1[4], t2[4], c) 166 t1[5], c = bits.Add64(t1[5], t2[5], c) 167 t1[6], c = bits.Add64(t1[6], t2[6], c) 168 t1[7], c = bits.Add64(t1[7], t2[7], c) 169 t1[8], _ = bits.Add64(t1[8], t2[8], c) 170 171 _, c = bits.Add64(t1[0], s[0], 0) 172 r[0], c = bits.Add64(t1[1], s[1], c) 173 r[1], c = bits.Add64(t1[2], s[2], c) 174 r[2], c = bits.Add64(t1[3], s[3], c) 175 r[3], c = bits.Add64(t1[4], s[4], c) 176 r[4], c = bits.Add64(t1[5], s[5], c) 177 r[5], c = bits.Add64(t1[6], s[6], c) 178 r[6], c = bits.Add64(t1[7], s[7], c) 179 r[7], _ = bits.Add64(t1[8], 0, c) 180 }