2018-12-03 23:07:01 +00:00
|
|
|
// +build noasm !amd64,!arm64
|
2018-07-23 23:18:38 +01:00
|
|
|
|
2018-09-11 12:02:29 +01:00
|
|
|
package p751
|
|
|
|
|
|
|
|
import (
|
2018-12-03 23:07:01 +00:00
|
|
|
. "github.com/henrydcase/nobs/dh/sidh/internal/arith"
|
2018-09-11 12:02:29 +01:00
|
|
|
. "github.com/henrydcase/nobs/dh/sidh/internal/isogeny"
|
|
|
|
)
|
2018-07-23 23:18:38 +01:00
|
|
|
|
|
|
|
// Compute z = x + y (mod p).
|
2018-09-11 12:02:29 +01:00
|
|
|
func fp751AddReduced(z, x, y *FpElement) {
|
2018-07-23 23:18:38 +01:00
|
|
|
var carry uint64
|
|
|
|
|
|
|
|
// z=x+y % p751
|
2018-09-11 12:02:29 +01:00
|
|
|
for i := 0; i < NumWords; i++ {
|
2018-12-03 23:07:01 +00:00
|
|
|
z[i], carry = Addc64(carry, x[i], y[i])
|
2018-07-23 23:18:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// z = z - p751x2
|
|
|
|
carry = 0
|
2018-09-11 12:02:29 +01:00
|
|
|
for i := 0; i < NumWords; i++ {
|
2018-12-03 23:07:01 +00:00
|
|
|
z[i], carry = Subc64(carry, z[i], p751x2[i])
|
2018-07-23 23:18:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// z = z + p751x2
|
|
|
|
mask := uint64(0 - carry)
|
|
|
|
carry = 0
|
2018-09-11 12:02:29 +01:00
|
|
|
for i := 0; i < NumWords; i++ {
|
2018-12-03 23:07:01 +00:00
|
|
|
z[i], carry = Addc64(carry, z[i], p751x2[i]&mask)
|
2018-07-23 23:18:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute z = x - y (mod p).
|
2018-09-11 12:02:29 +01:00
|
|
|
func fp751SubReduced(z, x, y *FpElement) {
|
2018-07-23 23:18:38 +01:00
|
|
|
var borrow uint64
|
|
|
|
|
2018-09-11 12:02:29 +01:00
|
|
|
for i := 0; i < NumWords; i++ {
|
2018-12-03 23:07:01 +00:00
|
|
|
z[i], borrow = Subc64(borrow, x[i], y[i])
|
2018-07-23 23:18:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
mask := uint64(0 - borrow)
|
|
|
|
borrow = 0
|
|
|
|
|
2018-09-11 12:02:29 +01:00
|
|
|
for i := 0; i < NumWords; i++ {
|
2018-12-03 23:07:01 +00:00
|
|
|
z[i], borrow = Addc64(borrow, z[i], p751x2[i]&mask)
|
2018-07-23 23:18:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Conditionally swaps bits in x and y in constant time.
|
|
|
|
// mask indicates bits to be swaped (set bits are swapped)
|
|
|
|
// For details see "Hackers Delight, 2.20"
|
|
|
|
//
|
|
|
|
// Implementation doesn't actually depend on a prime field.
|
2018-09-11 12:02:29 +01:00
|
|
|
func fp751ConditionalSwap(x, y *FpElement, mask uint8) {
|
2018-07-23 23:18:38 +01:00
|
|
|
var tmp, mask64 uint64
|
|
|
|
|
|
|
|
mask64 = 0 - uint64(mask)
|
|
|
|
for i := 0; i < len(x); i++ {
|
|
|
|
tmp = mask64 & (x[i] ^ y[i])
|
|
|
|
x[i] = tmp ^ x[i]
|
|
|
|
y[i] = tmp ^ y[i]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Perform Montgomery reduction: set z = x R^{-1} (mod 2*p)
|
|
|
|
// with R=2^768. Destroys the input value.
|
2018-09-11 12:02:29 +01:00
|
|
|
func fp751MontgomeryReduce(z *FpElement, x *FpElementX2) {
|
2018-07-23 23:18:38 +01:00
|
|
|
var carry, t, u, v uint64
|
2018-12-03 23:07:01 +00:00
|
|
|
var uv Uint128
|
2018-07-23 23:18:38 +01:00
|
|
|
var count int
|
|
|
|
|
|
|
|
count = 5 // number of 0 digits in the least significat part of p751 + 1
|
|
|
|
|
2018-09-11 12:02:29 +01:00
|
|
|
for i := 0; i < NumWords; i++ {
|
2018-07-23 23:18:38 +01:00
|
|
|
for j := 0; j < i; j++ {
|
|
|
|
if j < (i - count + 1) {
|
2018-12-03 23:07:01 +00:00
|
|
|
uv = Mul64(z[j], p751p1[i-j])
|
|
|
|
v, carry = Addc64(0, uv.L, v)
|
|
|
|
u, carry = Addc64(carry, uv.H, u)
|
2018-07-23 23:18:38 +01:00
|
|
|
t += carry
|
|
|
|
}
|
|
|
|
}
|
2018-12-03 23:07:01 +00:00
|
|
|
v, carry = Addc64(0, v, x[i])
|
|
|
|
u, carry = Addc64(carry, u, 0)
|
2018-07-23 23:18:38 +01:00
|
|
|
t += carry
|
|
|
|
|
|
|
|
z[i] = v
|
|
|
|
v = u
|
|
|
|
u = t
|
|
|
|
t = 0
|
|
|
|
}
|
|
|
|
|
2018-09-11 12:02:29 +01:00
|
|
|
for i := NumWords; i < 2*NumWords-1; i++ {
|
2018-07-23 23:18:38 +01:00
|
|
|
if count > 0 {
|
|
|
|
count--
|
|
|
|
}
|
2018-09-11 12:02:29 +01:00
|
|
|
for j := i - NumWords + 1; j < NumWords; j++ {
|
|
|
|
if j < (NumWords - count) {
|
2018-12-03 23:07:01 +00:00
|
|
|
uv = Mul64(z[j], p751p1[i-j])
|
|
|
|
v, carry = Addc64(0, uv.L, v)
|
|
|
|
u, carry = Addc64(carry, uv.H, u)
|
2018-07-23 23:18:38 +01:00
|
|
|
t += carry
|
|
|
|
}
|
|
|
|
}
|
2018-12-03 23:07:01 +00:00
|
|
|
v, carry = Addc64(0, v, x[i])
|
|
|
|
u, carry = Addc64(carry, u, 0)
|
2018-07-23 23:18:38 +01:00
|
|
|
|
|
|
|
t += carry
|
2018-09-11 12:02:29 +01:00
|
|
|
z[i-NumWords] = v
|
2018-07-23 23:18:38 +01:00
|
|
|
v = u
|
|
|
|
u = t
|
|
|
|
t = 0
|
|
|
|
}
|
2018-12-03 23:07:01 +00:00
|
|
|
v, carry = Addc64(0, v, x[2*NumWords-1])
|
2018-09-11 12:02:29 +01:00
|
|
|
z[NumWords-1] = v
|
2018-07-23 23:18:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Compute z = x * y.
|
2018-09-11 12:02:29 +01:00
|
|
|
func fp751Mul(z *FpElementX2, x, y *FpElement) {
|
2018-07-23 23:18:38 +01:00
|
|
|
var u, v, t uint64
|
|
|
|
var carry uint64
|
2018-12-03 23:07:01 +00:00
|
|
|
var uv Uint128
|
2018-07-23 23:18:38 +01:00
|
|
|
|
2018-09-11 12:02:29 +01:00
|
|
|
for i := uint64(0); i < NumWords; i++ {
|
2018-07-23 23:18:38 +01:00
|
|
|
for j := uint64(0); j <= i; j++ {
|
2018-12-03 23:07:01 +00:00
|
|
|
uv = Mul64(x[j], y[i-j])
|
|
|
|
v, carry = Addc64(0, uv.L, v)
|
|
|
|
u, carry = Addc64(carry, uv.H, u)
|
2018-07-23 23:18:38 +01:00
|
|
|
t += carry
|
|
|
|
}
|
|
|
|
z[i] = v
|
|
|
|
v = u
|
|
|
|
u = t
|
|
|
|
t = 0
|
|
|
|
}
|
|
|
|
|
2018-09-11 12:02:29 +01:00
|
|
|
for i := NumWords; i < (2*NumWords)-1; i++ {
|
|
|
|
for j := i - NumWords + 1; j < NumWords; j++ {
|
2018-12-03 23:07:01 +00:00
|
|
|
uv = Mul64(x[j], y[i-j])
|
|
|
|
v, carry = Addc64(0, uv.L, v)
|
|
|
|
u, carry = Addc64(carry, uv.H, u)
|
2018-07-23 23:18:38 +01:00
|
|
|
t += carry
|
|
|
|
}
|
|
|
|
z[i] = v
|
|
|
|
v = u
|
|
|
|
u = t
|
|
|
|
t = 0
|
|
|
|
}
|
2018-09-11 12:02:29 +01:00
|
|
|
z[2*NumWords-1] = v
|
2018-07-23 23:18:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Compute z = x + y, without reducing mod p.
|
2018-09-11 12:02:29 +01:00
|
|
|
func fp751AddLazy(z, x, y *FpElement) {
|
2018-07-23 23:18:38 +01:00
|
|
|
var carry uint64
|
2018-09-11 12:02:29 +01:00
|
|
|
for i := 0; i < NumWords; i++ {
|
2018-12-03 23:07:01 +00:00
|
|
|
z[i], carry = Addc64(carry, x[i], y[i])
|
2018-07-23 23:18:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute z = x + y, without reducing mod p.
|
2018-09-11 12:02:29 +01:00
|
|
|
func fp751X2AddLazy(z, x, y *FpElementX2) {
|
2018-07-23 23:18:38 +01:00
|
|
|
var carry uint64
|
2018-09-11 12:02:29 +01:00
|
|
|
for i := 0; i < 2*NumWords; i++ {
|
2018-12-03 23:07:01 +00:00
|
|
|
z[i], carry = Addc64(carry, x[i], y[i])
|
2018-07-23 23:18:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reduce a field element in [0, 2*p) to one in [0,p).
|
2018-09-11 12:02:29 +01:00
|
|
|
func fp751StrongReduce(x *FpElement) {
|
2018-07-23 23:18:38 +01:00
|
|
|
var borrow, mask uint64
|
2018-09-11 12:02:29 +01:00
|
|
|
for i := 0; i < NumWords; i++ {
|
2018-12-03 23:07:01 +00:00
|
|
|
x[i], borrow = Subc64(borrow, x[i], p751[i])
|
2018-07-23 23:18:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Sets all bits if borrow = 1
|
|
|
|
mask = 0 - borrow
|
|
|
|
borrow = 0
|
2018-09-11 12:02:29 +01:00
|
|
|
for i := 0; i < NumWords; i++ {
|
2018-12-03 23:07:01 +00:00
|
|
|
x[i], borrow = Addc64(borrow, x[i], p751[i]&mask)
|
2018-07-23 23:18:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute z = x - y, without reducing mod p.
|
2018-09-11 12:02:29 +01:00
|
|
|
func fp751X2SubLazy(z, x, y *FpElementX2) {
|
2018-07-23 23:18:38 +01:00
|
|
|
var borrow, mask uint64
|
|
|
|
for i := 0; i < len(z); i++ {
|
2018-12-03 23:07:01 +00:00
|
|
|
z[i], borrow = Subc64(borrow, x[i], y[i])
|
2018-07-23 23:18:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Sets all bits if borrow = 1
|
|
|
|
mask = 0 - borrow
|
|
|
|
borrow = 0
|
2018-09-11 12:02:29 +01:00
|
|
|
for i := NumWords; i < len(z); i++ {
|
2018-12-03 23:07:01 +00:00
|
|
|
z[i], borrow = Addc64(borrow, z[i], p751[i-NumWords]&mask)
|
2018-07-23 23:18:38 +01:00
|
|
|
}
|
|
|
|
}
|