github.com/cloudflare/circl@v1.5.0/math/fp25519/fp_generic.go (about) 1 package fp25519 2 3 import ( 4 "encoding/binary" 5 "math/bits" 6 ) 7 8 func cmovGeneric(x, y *Elt, n uint) { 9 m := -uint64(n & 0x1) 10 x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) 11 x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) 12 x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) 13 x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) 14 15 y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8]) 16 y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8]) 17 y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8]) 18 y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8]) 19 20 x0 = (x0 &^ m) | (y0 & m) 21 x1 = (x1 &^ m) | (y1 & m) 22 x2 = (x2 &^ m) | (y2 & m) 23 x3 = (x3 &^ m) | (y3 & m) 24 25 binary.LittleEndian.PutUint64(x[0*8:1*8], x0) 26 binary.LittleEndian.PutUint64(x[1*8:2*8], x1) 27 binary.LittleEndian.PutUint64(x[2*8:3*8], x2) 28 binary.LittleEndian.PutUint64(x[3*8:4*8], x3) 29 } 30 31 func cswapGeneric(x, y *Elt, n uint) { 32 m := -uint64(n & 0x1) 33 x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) 34 x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) 35 x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) 36 x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) 37 38 y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8]) 39 y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8]) 40 y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8]) 41 y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8]) 42 43 t0 := m & (x0 ^ y0) 44 t1 := m & (x1 ^ y1) 45 t2 := m & (x2 ^ y2) 46 t3 := m & (x3 ^ y3) 47 x0 ^= t0 48 x1 ^= t1 49 x2 ^= t2 50 x3 ^= t3 51 y0 ^= t0 52 y1 ^= t1 53 y2 ^= t2 54 y3 ^= t3 55 56 binary.LittleEndian.PutUint64(x[0*8:1*8], x0) 57 binary.LittleEndian.PutUint64(x[1*8:2*8], x1) 58 binary.LittleEndian.PutUint64(x[2*8:3*8], x2) 59 binary.LittleEndian.PutUint64(x[3*8:4*8], x3) 60 61 binary.LittleEndian.PutUint64(y[0*8:1*8], y0) 62 binary.LittleEndian.PutUint64(y[1*8:2*8], y1) 63 binary.LittleEndian.PutUint64(y[2*8:3*8], y2) 64 binary.LittleEndian.PutUint64(y[3*8:4*8], y3) 65 } 66 67 func addGeneric(z, x, y *Elt) { 68 x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) 69 x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) 70 x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) 71 x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) 72 73 y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8]) 74 y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8]) 75 y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8]) 76 y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8]) 77 78 z0, c0 := bits.Add64(x0, y0, 0) 79 z1, c1 := bits.Add64(x1, y1, c0) 80 z2, c2 := bits.Add64(x2, y2, c1) 81 z3, c3 := bits.Add64(x3, y3, c2) 82 83 z0, c0 = bits.Add64(z0, (-c3)&38, 0) 84 z1, c1 = bits.Add64(z1, 0, c0) 85 z2, c2 = bits.Add64(z2, 0, c1) 86 z3, c3 = bits.Add64(z3, 0, c2) 87 z0, _ = bits.Add64(z0, (-c3)&38, 0) 88 89 binary.LittleEndian.PutUint64(z[0*8:1*8], z0) 90 binary.LittleEndian.PutUint64(z[1*8:2*8], z1) 91 binary.LittleEndian.PutUint64(z[2*8:3*8], z2) 92 binary.LittleEndian.PutUint64(z[3*8:4*8], z3) 93 } 94 95 func subGeneric(z, x, y *Elt) { 96 x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) 97 x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) 98 x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) 99 x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) 100 101 y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8]) 102 y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8]) 103 y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8]) 104 y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8]) 105 106 z0, c0 := bits.Sub64(x0, y0, 0) 107 z1, c1 := bits.Sub64(x1, y1, c0) 108 z2, c2 := bits.Sub64(x2, y2, c1) 109 z3, c3 := bits.Sub64(x3, y3, c2) 110 111 z0, c0 = bits.Sub64(z0, (-c3)&38, 0) 112 z1, c1 = bits.Sub64(z1, 0, c0) 113 z2, c2 = bits.Sub64(z2, 0, c1) 114 z3, c3 = bits.Sub64(z3, 0, c2) 115 z0, _ = bits.Sub64(z0, (-c3)&38, 0) 116 117 binary.LittleEndian.PutUint64(z[0*8:1*8], z0) 118 binary.LittleEndian.PutUint64(z[1*8:2*8], z1) 119 binary.LittleEndian.PutUint64(z[2*8:3*8], z2) 120 binary.LittleEndian.PutUint64(z[3*8:4*8], z3) 121 } 122 123 func addsubGeneric(x, y *Elt) { 124 z := &Elt{} 125 addGeneric(z, x, y) 126 subGeneric(y, x, y) 127 *x = *z 128 } 129 130 func mulGeneric(z, x, y *Elt) { 131 x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) 132 x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) 133 x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) 134 x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) 135 136 y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8]) 137 y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8]) 138 y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8]) 139 y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8]) 140 141 yi := y0 142 h0, l0 := bits.Mul64(x0, yi) 143 h1, l1 := bits.Mul64(x1, yi) 144 h2, l2 := bits.Mul64(x2, yi) 145 h3, l3 := bits.Mul64(x3, yi) 146 147 z0 := l0 148 a0, c0 := bits.Add64(h0, l1, 0) 149 a1, c1 := bits.Add64(h1, l2, c0) 150 a2, c2 := bits.Add64(h2, l3, c1) 151 a3, _ := bits.Add64(h3, 0, c2) 152 153 yi = y1 154 h0, l0 = bits.Mul64(x0, yi) 155 h1, l1 = bits.Mul64(x1, yi) 156 h2, l2 = bits.Mul64(x2, yi) 157 h3, l3 = bits.Mul64(x3, yi) 158 159 z1, c0 := bits.Add64(a0, l0, 0) 160 h0, c1 = bits.Add64(h0, l1, c0) 161 h1, c2 = bits.Add64(h1, l2, c1) 162 h2, c3 := bits.Add64(h2, l3, c2) 163 h3, _ = bits.Add64(h3, 0, c3) 164 165 a0, c0 = bits.Add64(a1, h0, 0) 166 a1, c1 = bits.Add64(a2, h1, c0) 167 a2, c2 = bits.Add64(a3, h2, c1) 168 a3, _ = bits.Add64(0, h3, c2) 169 170 yi = y2 171 h0, l0 = bits.Mul64(x0, yi) 172 h1, l1 = bits.Mul64(x1, yi) 173 h2, l2 = bits.Mul64(x2, yi) 174 h3, l3 = bits.Mul64(x3, yi) 175 176 z2, c0 := bits.Add64(a0, l0, 0) 177 h0, c1 = bits.Add64(h0, l1, c0) 178 h1, c2 = bits.Add64(h1, l2, c1) 179 h2, c3 = bits.Add64(h2, l3, c2) 180 h3, _ = bits.Add64(h3, 0, c3) 181 182 a0, c0 = bits.Add64(a1, h0, 0) 183 a1, c1 = bits.Add64(a2, h1, c0) 184 a2, c2 = bits.Add64(a3, h2, c1) 185 a3, _ = bits.Add64(0, h3, c2) 186 187 yi = y3 188 h0, l0 = bits.Mul64(x0, yi) 189 h1, l1 = bits.Mul64(x1, yi) 190 h2, l2 = bits.Mul64(x2, yi) 191 h3, l3 = bits.Mul64(x3, yi) 192 193 z3, c0 := bits.Add64(a0, l0, 0) 194 h0, c1 = bits.Add64(h0, l1, c0) 195 h1, c2 = bits.Add64(h1, l2, c1) 196 h2, c3 = bits.Add64(h2, l3, c2) 197 h3, _ = bits.Add64(h3, 0, c3) 198 199 z4, c0 := bits.Add64(a1, h0, 0) 200 z5, c1 := bits.Add64(a2, h1, c0) 201 z6, c2 := bits.Add64(a3, h2, c1) 202 z7, _ := bits.Add64(0, h3, c2) 203 204 red64(z, z0, z1, z2, z3, z4, z5, z6, z7) 205 } 206 207 func sqrGeneric(z, x *Elt) { 208 x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) 209 x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) 210 x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) 211 x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) 212 213 h0, a0 := bits.Mul64(x0, x1) 214 h1, l1 := bits.Mul64(x0, x2) 215 h2, l2 := bits.Mul64(x0, x3) 216 h3, l3 := bits.Mul64(x3, x1) 217 h4, l4 := bits.Mul64(x3, x2) 218 h, l := bits.Mul64(x1, x2) 219 220 a1, c0 := bits.Add64(l1, h0, 0) 221 a2, c1 := bits.Add64(l2, h1, c0) 222 a3, c2 := bits.Add64(l3, h2, c1) 223 a4, c3 := bits.Add64(l4, h3, c2) 224 a5, _ := bits.Add64(h4, 0, c3) 225 226 a2, c0 = bits.Add64(a2, l, 0) 227 a3, c1 = bits.Add64(a3, h, c0) 228 a4, c2 = bits.Add64(a4, 0, c1) 229 a5, c3 = bits.Add64(a5, 0, c2) 230 a6, _ := bits.Add64(0, 0, c3) 231 232 a0, c0 = bits.Add64(a0, a0, 0) 233 a1, c1 = bits.Add64(a1, a1, c0) 234 a2, c2 = bits.Add64(a2, a2, c1) 235 a3, c3 = bits.Add64(a3, a3, c2) 236 a4, c4 := bits.Add64(a4, a4, c3) 237 a5, c5 := bits.Add64(a5, a5, c4) 238 a6, _ = bits.Add64(a6, a6, c5) 239 240 b1, b0 := bits.Mul64(x0, x0) 241 b3, b2 := bits.Mul64(x1, x1) 242 b5, b4 := bits.Mul64(x2, x2) 243 b7, b6 := bits.Mul64(x3, x3) 244 245 b1, c0 = bits.Add64(b1, a0, 0) 246 b2, c1 = bits.Add64(b2, a1, c0) 247 b3, c2 = bits.Add64(b3, a2, c1) 248 b4, c3 = bits.Add64(b4, a3, c2) 249 b5, c4 = bits.Add64(b5, a4, c3) 250 b6, c5 = bits.Add64(b6, a5, c4) 251 b7, _ = bits.Add64(b7, a6, c5) 252 253 red64(z, b0, b1, b2, b3, b4, b5, b6, b7) 254 } 255 256 func modpGeneric(x *Elt) { 257 x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8]) 258 x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8]) 259 x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8]) 260 x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8]) 261 262 // CX = C[255] ? 38 : 19 263 cx := uint64(19) << (x3 >> 63) 264 // PUT BIT 255 IN CARRY FLAG AND CLEAR 265 x3 &^= 1 << 63 266 267 x0, c0 := bits.Add64(x0, cx, 0) 268 x1, c1 := bits.Add64(x1, 0, c0) 269 x2, c2 := bits.Add64(x2, 0, c1) 270 x3, _ = bits.Add64(x3, 0, c2) 271 272 // TEST FOR BIT 255 AGAIN; ONLY TRIGGERED ON OVERFLOW MODULO 2^255-19 273 // cx = C[255] ? 0 : 19 274 cx = uint64(19) &^ (-(x3 >> 63)) 275 // CLEAR BIT 255 276 x3 &^= 1 << 63 277 278 x0, c0 = bits.Sub64(x0, cx, 0) 279 x1, c1 = bits.Sub64(x1, 0, c0) 280 x2, c2 = bits.Sub64(x2, 0, c1) 281 x3, _ = bits.Sub64(x3, 0, c2) 282 283 binary.LittleEndian.PutUint64(x[0*8:1*8], x0) 284 binary.LittleEndian.PutUint64(x[1*8:2*8], x1) 285 binary.LittleEndian.PutUint64(x[2*8:3*8], x2) 286 binary.LittleEndian.PutUint64(x[3*8:4*8], x3) 287 } 288 289 func red64(z *Elt, x0, x1, x2, x3, x4, x5, x6, x7 uint64) { 290 h0, l0 := bits.Mul64(x4, 38) 291 h1, l1 := bits.Mul64(x5, 38) 292 h2, l2 := bits.Mul64(x6, 38) 293 h3, l3 := bits.Mul64(x7, 38) 294 295 l1, c0 := bits.Add64(h0, l1, 0) 296 l2, c1 := bits.Add64(h1, l2, c0) 297 l3, c2 := bits.Add64(h2, l3, c1) 298 l4, _ := bits.Add64(h3, 0, c2) 299 300 l0, c0 = bits.Add64(l0, x0, 0) 301 l1, c1 = bits.Add64(l1, x1, c0) 302 l2, c2 = bits.Add64(l2, x2, c1) 303 l3, c3 := bits.Add64(l3, x3, c2) 304 l4, _ = bits.Add64(l4, 0, c3) 305 306 _, l4 = bits.Mul64(l4, 38) 307 l0, c0 = bits.Add64(l0, l4, 0) 308 z1, c1 := bits.Add64(l1, 0, c0) 309 z2, c2 := bits.Add64(l2, 0, c1) 310 z3, c3 := bits.Add64(l3, 0, c2) 311 z0, _ := bits.Add64(l0, (-c3)&38, 0) 312 313 binary.LittleEndian.PutUint64(z[0*8:1*8], z0) 314 binary.LittleEndian.PutUint64(z[1*8:2*8], z1) 315 binary.LittleEndian.PutUint64(z[2*8:3*8], z2) 316 binary.LittleEndian.PutUint64(z[3*8:4*8], z3) 317 }