1 package csidh
2
3 import (
4 "math/bits"
5 )
6
7
8
9
10
11 func ctPick64(which uint64, in1, in2 uint64) uint64 {
12 return (in1 & which) | (in2 & ^which)
13 }
14
15
16
17 func ctIsNonZero64(i uint64) int {
18
19
20
21
22 return int((i | (^(i - 1))) >> 63)
23 }
24
25
26 func isLess(x, y *fp) bool {
27 for i := numWords - 1; i >= 0; i-- {
28 v, c := bits.Sub64(y[i], x[i], 0)
29 if c != 0 {
30 return false
31 }
32 if v != 0 {
33 return true
34 }
35 }
36
37 return false
38 }
39
40
41 func addRdc(r, x, y *fp) {
42 var c uint64
43 var t fp
44 r[0], c = bits.Add64(x[0], y[0], 0)
45 r[1], c = bits.Add64(x[1], y[1], c)
46 r[2], c = bits.Add64(x[2], y[2], c)
47 r[3], c = bits.Add64(x[3], y[3], c)
48 r[4], c = bits.Add64(x[4], y[4], c)
49 r[5], c = bits.Add64(x[5], y[5], c)
50 r[6], c = bits.Add64(x[6], y[6], c)
51 r[7], _ = bits.Add64(x[7], y[7], c)
52
53 t[0], c = bits.Sub64(r[0], p[0], 0)
54 t[1], c = bits.Sub64(r[1], p[1], c)
55 t[2], c = bits.Sub64(r[2], p[2], c)
56 t[3], c = bits.Sub64(r[3], p[3], c)
57 t[4], c = bits.Sub64(r[4], p[4], c)
58 t[5], c = bits.Sub64(r[5], p[5], c)
59 t[6], c = bits.Sub64(r[6], p[6], c)
60 t[7], c = bits.Sub64(r[7], p[7], c)
61
62 w := 0 - c
63 r[0] = ctPick64(w, r[0], t[0])
64 r[1] = ctPick64(w, r[1], t[1])
65 r[2] = ctPick64(w, r[2], t[2])
66 r[3] = ctPick64(w, r[3], t[3])
67 r[4] = ctPick64(w, r[4], t[4])
68 r[5] = ctPick64(w, r[5], t[5])
69 r[6] = ctPick64(w, r[6], t[6])
70 r[7] = ctPick64(w, r[7], t[7])
71 }
72
73
74 func sub512(r, x, y *fp) uint64 {
75 var c uint64
76 r[0], c = bits.Sub64(x[0], y[0], 0)
77 r[1], c = bits.Sub64(x[1], y[1], c)
78 r[2], c = bits.Sub64(x[2], y[2], c)
79 r[3], c = bits.Sub64(x[3], y[3], c)
80 r[4], c = bits.Sub64(x[4], y[4], c)
81 r[5], c = bits.Sub64(x[5], y[5], c)
82 r[6], c = bits.Sub64(x[6], y[6], c)
83 r[7], c = bits.Sub64(x[7], y[7], c)
84 return c
85 }
86
87
88 func subRdc(r, x, y *fp) {
89 var c uint64
90
91
92
93 r[0], c = bits.Sub64(x[0], y[0], 0)
94 r[1], c = bits.Sub64(x[1], y[1], c)
95 r[2], c = bits.Sub64(x[2], y[2], c)
96 r[3], c = bits.Sub64(x[3], y[3], c)
97 r[4], c = bits.Sub64(x[4], y[4], c)
98 r[5], c = bits.Sub64(x[5], y[5], c)
99 r[6], c = bits.Sub64(x[6], y[6], c)
100 r[7], c = bits.Sub64(x[7], y[7], c)
101
102
103 w := 0 - c
104 r[0], c = bits.Add64(r[0], ctPick64(w, p[0], 0), 0)
105 r[1], c = bits.Add64(r[1], ctPick64(w, p[1], 0), c)
106 r[2], c = bits.Add64(r[2], ctPick64(w, p[2], 0), c)
107 r[3], c = bits.Add64(r[3], ctPick64(w, p[3], 0), c)
108 r[4], c = bits.Add64(r[4], ctPick64(w, p[4], 0), c)
109 r[5], c = bits.Add64(r[5], ctPick64(w, p[5], 0), c)
110 r[6], c = bits.Add64(r[6], ctPick64(w, p[6], 0), c)
111 r[7], _ = bits.Add64(r[7], ctPick64(w, p[7], 0), c)
112 }
113
114
115
116
117
118 func modExpRdcCommon(r, b, e *fp, fpBitLen int) {
119 var precomp [16]fp
120 var t fp
121 var c uint64
122
123
124
125
126 precomp[0] = one
127 precomp[1] = *b
128 for i := 2; i < 16; i = i + 2 {
129
130
131 mulRdc(&precomp[i], &precomp[i/2], &precomp[i/2])
132 mulRdc(&precomp[i+1], &precomp[i], b)
133 }
134
135 *r = one
136 for i := fpBitLen/4 - 1; i >= 0; i-- {
137 for j := 0; j < 4; j++ {
138 mulRdc(r, r, r)
139 }
140
141 idx := (e[i/16] >> uint((i%16)*4)) & 15
142 mulRdc(r, r, &precomp[idx])
143 }
144
145
146 t[0], c = bits.Sub64(r[0], p[0], 0)
147 t[1], c = bits.Sub64(r[1], p[1], c)
148 t[2], c = bits.Sub64(r[2], p[2], c)
149 t[3], c = bits.Sub64(r[3], p[3], c)
150 t[4], c = bits.Sub64(r[4], p[4], c)
151 t[5], c = bits.Sub64(r[5], p[5], c)
152 t[6], c = bits.Sub64(r[6], p[6], c)
153 t[7], c = bits.Sub64(r[7], p[7], c)
154
155 w := 0 - c
156 r[0] = ctPick64(w, r[0], t[0])
157 r[1] = ctPick64(w, r[1], t[1])
158 r[2] = ctPick64(w, r[2], t[2])
159 r[3] = ctPick64(w, r[3], t[3])
160 r[4] = ctPick64(w, r[4], t[4])
161 r[5] = ctPick64(w, r[5], t[5])
162 r[6] = ctPick64(w, r[6], t[6])
163 r[7] = ctPick64(w, r[7], t[7])
164 }
165
166
167
168 func modExpRdc512(r, b, e *fp) {
169 modExpRdcCommon(r, b, e, 512)
170 }
171
172
173
174 func modExpRdc64(r, b *fp, e uint64) {
175 modExpRdcCommon(r, b, &fp{e}, 64)
176 }
177
178
179
180
181
182
183
184
185
186
187
188
189 func (v *fp) isNonQuadRes() int {
190 var res fp
191 var b uint64
192
193 modExpRdc512(&res, v, &pMin1By2)
194 for i := range res {
195 b |= res[i] ^ one[i]
196 }
197
198 return ctIsNonZero64(b)
199 }
200
201
202
203 func (v *fp) isZero() bool {
204 var r uint64
205 for i := 0; i < numWords; i++ {
206 r |= v[i]
207 }
208 return ctIsNonZero64(r) == 0
209 }
210
211
212 func (v *fp) equal(in *fp) bool {
213 var r uint64
214 for i := range v {
215 r |= v[i] ^ in[i]
216 }
217 return ctIsNonZero64(r) == 0
218 }
219
View as plain text