You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 rivejä
3.8 KiB

  1. package sike
  2. import (
  3. "math/bits"
  4. )
  5. // Fp implementation
  6. // Compute z = x + y (mod 2*p).
  7. func fpAddRdc(z, x, y *Fp) {
  8. var carry uint64
  9. // z=x+y % p503
  10. for i := 0; i < FP_WORDS; i++ {
  11. z[i], carry = bits.Add64(x[i], y[i], carry)
  12. }
  13. // z = z - pX2
  14. carry = 0
  15. for i := 0; i < FP_WORDS; i++ {
  16. z[i], carry = bits.Sub64(z[i], pX2[i], carry)
  17. }
  18. // if z<0 add pX2 back
  19. mask := uint64(0 - carry)
  20. carry = 0
  21. for i := 0; i < FP_WORDS; i++ {
  22. z[i], carry = bits.Add64(z[i], pX2[i]&mask, carry)
  23. }
  24. }
  25. // Compute z = x - y (mod 2*p).
  26. func fpSubRdc(z, x, y *Fp) {
  27. var borrow uint64
  28. // z = z - pX2
  29. for i := 0; i < FP_WORDS; i++ {
  30. z[i], borrow = bits.Sub64(x[i], y[i], borrow)
  31. }
  32. // if z<0 add pX2 back
  33. mask := uint64(0 - borrow)
  34. borrow = 0
  35. for i := 0; i < FP_WORDS; i++ {
  36. z[i], borrow = bits.Add64(z[i], pX2[i]&mask, borrow)
  37. }
  38. }
  39. // Reduce a field element in [0, 2*p) to one in [0,p).
  40. func fpRdcP(x *Fp) {
  41. var borrow, mask uint64
  42. for i := 0; i < FP_WORDS; i++ {
  43. x[i], borrow = bits.Sub64(x[i], p[i], borrow)
  44. }
  45. // Sets all bits if borrow = 1
  46. mask = 0 - borrow
  47. borrow = 0
  48. for i := 0; i < FP_WORDS; i++ {
  49. x[i], borrow = bits.Add64(x[i], p[i]&mask, borrow)
  50. }
  51. }
  52. // Implementation doesn't actually depend on a prime field.
  53. func fpSwapCond(x, y *Fp, mask uint8) {
  54. if mask != 0 {
  55. var tmp Fp
  56. copy(tmp[:], y[:])
  57. copy(y[:], x[:])
  58. copy(x[:], tmp[:])
  59. }
  60. }
  61. // Compute z = x * y.
  62. func fpMul(z *FpX2, x, y *Fp) {
  63. var carry, t, u, v uint64
  64. var hi, lo uint64
  65. for i := uint64(0); i < FP_WORDS; i++ {
  66. for j := uint64(0); j <= i; j++ {
  67. hi, lo = bits.Mul64(x[j], y[i-j])
  68. v, carry = bits.Add64(lo, v, 0)
  69. u, carry = bits.Add64(hi, u, carry)
  70. t += carry
  71. }
  72. z[i] = v
  73. v = u
  74. u = t
  75. t = 0
  76. }
  77. for i := FP_WORDS; i < (2*FP_WORDS)-1; i++ {
  78. for j := i - FP_WORDS + 1; j < FP_WORDS; j++ {
  79. hi, lo = bits.Mul64(x[j], y[i-j])
  80. v, carry = bits.Add64(lo, v, 0)
  81. u, carry = bits.Add64(hi, u, carry)
  82. t += carry
  83. }
  84. z[i] = v
  85. v = u
  86. u = t
  87. t = 0
  88. }
  89. z[2*FP_WORDS-1] = v
  90. }
  91. // Perform Montgomery reduction: set z = x R^{-1} (mod 2*p)
  92. // with R=2^512. Destroys the input value.
  93. func fpMontRdc(z *Fp, x *FpX2) {
  94. var carry, t, u, v uint64
  95. var hi, lo uint64
  96. var count int
  97. count = 3 // number of 0 digits in the least significat part of p503 + 1
  98. for i := 0; i < FP_WORDS; i++ {
  99. for j := 0; j < i; j++ {
  100. if j < (i - count + 1) {
  101. hi, lo = bits.Mul64(z[j], p1[i-j])
  102. v, carry = bits.Add64(lo, v, 0)
  103. u, carry = bits.Add64(hi, u, carry)
  104. t += carry
  105. }
  106. }
  107. v, carry = bits.Add64(v, x[i], 0)
  108. u, carry = bits.Add64(u, 0, carry)
  109. t += carry
  110. z[i] = v
  111. v = u
  112. u = t
  113. t = 0
  114. }
  115. for i := FP_WORDS; i < 2*FP_WORDS-1; i++ {
  116. if count > 0 {
  117. count--
  118. }
  119. for j := i - FP_WORDS + 1; j < FP_WORDS; j++ {
  120. if j < (FP_WORDS - count) {
  121. hi, lo = bits.Mul64(z[j], p1[i-j])
  122. v, carry = bits.Add64(lo, v, 0)
  123. u, carry = bits.Add64(hi, u, carry)
  124. t += carry
  125. }
  126. }
  127. v, carry = bits.Add64(v, x[i], 0)
  128. u, carry = bits.Add64(u, 0, carry)
  129. t += carry
  130. z[i-FP_WORDS] = v
  131. v = u
  132. u = t
  133. t = 0
  134. }
  135. v, carry = bits.Add64(v, x[2*FP_WORDS-1], 0)
  136. z[FP_WORDS-1] = v
  137. }
  138. // Compute z = x + y, without reducing mod p.
  139. func fp2Add(z, x, y *FpX2) {
  140. var carry uint64
  141. for i := 0; i < 2*FP_WORDS; i++ {
  142. z[i], carry = bits.Add64(x[i], y[i], carry)
  143. }
  144. }
  145. // Compute z = x - y, without reducing mod p.
  146. func fp2Sub(z, x, y *FpX2) {
  147. var borrow, mask uint64
  148. for i := 0; i < 2*FP_WORDS; i++ {
  149. z[i], borrow = bits.Sub64(x[i], y[i], borrow)
  150. }
  151. // Sets all bits if borrow = 1
  152. mask = 0 - borrow
  153. borrow = 0
  154. for i := FP_WORDS; i < 2*FP_WORDS; i++ {
  155. z[i], borrow = bits.Add64(z[i], p[i-FP_WORDS]&mask, borrow)
  156. }
  157. }
  158. // Montgomery multiplication. Input values must be already
  159. // in Montgomery domain.
  160. func fpMulRdc(dest, lhs, rhs *Fp) {
  161. a := lhs // = a*R
  162. b := rhs // = b*R
  163. var ab FpX2
  164. fpMul(&ab, a, b) // = a*b*R*R
  165. fpMontRdc(dest, &ab) // = a*b*R mod p
  166. }