...
1
2
3 package internal
4
5 import (
6 "encoding/binary"
7
8 "github.com/cloudflare/circl/internal/sha3"
9 "github.com/cloudflare/circl/sign/dilithium/internal/common"
10 "github.com/cloudflare/circl/simd/keccakf1600"
11 )
12
13
14
15 var DeriveX4Available = keccakf1600.IsEnabledX4() && !UseAES
16
17
18
19
20
21 func PolyDeriveUniformX4(ps [4]*common.Poly, seed *[32]byte, nonces [4]uint16) {
22 var perm keccakf1600.StateX4
23 state := perm.Initialize(false)
24
25
26 for i := 0; i < 4; i++ {
27 v := binary.LittleEndian.Uint64(seed[8*i : 8*(i+1)])
28 for j := 0; j < 4; j++ {
29 state[i*4+j] = v
30 }
31 }
32
33
34
35
36 for j := 0; j < 4; j++ {
37 state[4*4+j] = uint64(nonces[j]) | (0x1f << 16)
38 state[20*4+j] = 0x80 << 56
39 }
40
41 var idx [4]int
42 for j := 0; j < 4; j++ {
43 if ps[j] == nil {
44 idx[j] = common.N
45 }
46 }
47
48 done := false
49 for !done {
50
51
52 perm.Permute()
53
54 done = true
55
56 PolyLoop:
57 for j := 0; j < 4; j++ {
58 if idx[j] == common.N {
59 continue
60 }
61 for i := 0; i < 7; i++ {
62 var t [8]uint32
63 t[0] = uint32(state[i*3*4+j] & 0x7fffff)
64 t[1] = uint32((state[i*3*4+j] >> 24) & 0x7fffff)
65 t[2] = uint32((state[i*3*4+j] >> 48) |
66 ((state[(i*3+1)*4+j] & 0x7f) << 16))
67 t[3] = uint32((state[(i*3+1)*4+j] >> 8) & 0x7fffff)
68 t[4] = uint32((state[(i*3+1)*4+j] >> 32) & 0x7fffff)
69 t[5] = uint32((state[(i*3+1)*4+j] >> 56) |
70 ((state[(i*3+2)*4+j] & 0x7fff) << 8))
71 t[6] = uint32((state[(i*3+2)*4+j] >> 16) & 0x7fffff)
72 t[7] = uint32((state[(i*3+2)*4+j] >> 40) & 0x7fffff)
73
74 for k := 0; k < 8; k++ {
75 if t[k] < common.Q {
76 ps[j][idx[j]] = t[k]
77 idx[j]++
78 if idx[j] == common.N {
79 continue PolyLoop
80 }
81 }
82 }
83 }
84 done = false
85 }
86 }
87 }
88
89
90
91
92 func PolyDeriveUniform(p *common.Poly, seed *[32]byte, nonce uint16) {
93 var i, length int
94 var buf [12 * 16]byte
95
96 if UseAES {
97 length = 12 * 16
98 } else {
99 length = 168
100 }
101
102 sample := func() {
103
104 for j := 0; j < length && i < common.N; j += 3 {
105 t := (uint32(buf[j]) | (uint32(buf[j+1]) << 8) |
106 (uint32(buf[j+2]) << 16)) & 0x7fffff
107
108
109 if t < common.Q {
110 p[i] = t
111 i++
112 }
113 }
114 }
115
116 if UseAES {
117 h := common.NewAesStream128(seed, nonce)
118
119 for i < common.N {
120 h.SqueezeInto(buf[:length])
121 sample()
122 }
123 } else {
124 var iv [32 + 2]byte
125 h := sha3.NewShake128()
126 copy(iv[:32], seed[:])
127 iv[32] = uint8(nonce)
128 iv[33] = uint8(nonce >> 8)
129 _, _ = h.Write(iv[:])
130
131 for i < common.N {
132 _, _ = h.Read(buf[:168])
133 sample()
134 }
135 }
136 }
137
138
139
140
141
142 func PolyDeriveUniformLeqEta(p *common.Poly, seed *[64]byte, nonce uint16) {
143
144 var i, length int
145 var buf [9 * 16]byte
146
147 if UseAES {
148 length = 9 * 16
149 } else {
150 length = 136
151 }
152
153 sample := func() {
154
155 for j := 0; j < length && i < common.N; j++ {
156 t1 := uint32(buf[j]) & 15
157 t2 := uint32(buf[j]) >> 4
158 if Eta == 2 {
159 if t1 <= 14 {
160 t1 -= ((205 * t1) >> 10) * 5
161 p[i] = common.Q + Eta - t1
162 i++
163 }
164 if t2 <= 14 && i < common.N {
165 t2 -= ((205 * t2) >> 10) * 5
166 p[i] = common.Q + Eta - t2
167 i++
168 }
169 } else if Eta == 4 {
170 if t1 <= 2*Eta {
171 p[i] = common.Q + Eta - t1
172 i++
173 }
174 if t2 <= 2*Eta && i < common.N {
175 p[i] = common.Q + Eta - t2
176 i++
177 }
178 } else {
179 panic("unsupported η")
180 }
181 }
182 }
183
184 if UseAES {
185 h := common.NewAesStream256(seed, nonce)
186
187 for i < common.N {
188 h.SqueezeInto(buf[:length])
189 sample()
190 }
191 } else {
192 var iv [64 + 2]byte
193
194 h := sha3.NewShake256()
195 copy(iv[:64], seed[:])
196 iv[64] = uint8(nonce)
197 iv[65] = uint8(nonce >> 8)
198
199
200 _, _ = h.Write(iv[:])
201
202 for i < common.N {
203 _, _ = h.Read(buf[:136])
204 sample()
205 }
206 }
207 }
208
209
210
211
212
213 func VecLDeriveUniformLeGamma1(v *VecL, seed *[64]byte, nonce uint16) {
214 for i := 0; i < L; i++ {
215 PolyDeriveUniformLeGamma1(&v[i], seed, nonce+uint16(i))
216 }
217 }
218
219
220
221
222
223 func PolyDeriveUniformLeGamma1(p *common.Poly, seed *[64]byte, nonce uint16) {
224 var buf [PolyLeGamma1Size]byte
225
226 if UseAES {
227 h := common.NewAesStream256(seed, nonce)
228 h.SqueezeInto(buf[:])
229 } else {
230 var iv [66]byte
231 h := sha3.NewShake256()
232 copy(iv[:64], seed[:])
233 iv[64] = uint8(nonce)
234 iv[65] = uint8(nonce >> 8)
235 _, _ = h.Write(iv[:])
236 _, _ = h.Read(buf[:])
237 }
238
239 PolyUnpackLeGamma1(p, buf[:])
240 }
241
242
243
244
245
246
247
248
249 func PolyDeriveUniformBallX4(ps [4]*common.Poly, seed *[32]byte) {
250 var perm keccakf1600.StateX4
251 state := perm.Initialize(false)
252
253
254 for i := 0; i < 4; i++ {
255 v := binary.LittleEndian.Uint64(seed[8*i : 8*(i+1)])
256 for j := 0; j < 4; j++ {
257 state[i*4+j] = v
258 }
259 }
260
261
262 for j := 0; j < 4; j++ {
263 state[4*4+j] ^= 0x1f
264 state[16*4+j] ^= 0x80 << 56
265 }
266 perm.Permute()
267
268 var signs [4]uint64
269 var idx [4]uint16
270
271 for j := 0; j < 4; j++ {
272 if ps[j] != nil {
273 signs[j] = state[j]
274 *ps[j] = common.Poly{}
275 idx[j] = common.N - Tau
276 } else {
277 idx[j] = common.N
278 }
279 }
280
281 stateOffset := 1
282 for {
283 done := true
284
285 PolyLoop:
286 for j := 0; j < 4; j++ {
287 if idx[j] == common.N {
288 continue
289 }
290
291 for i := stateOffset; i < 17; i++ {
292 var bs [8]byte
293 binary.LittleEndian.PutUint64(bs[:], state[4*i+j])
294 for k := 0; k < 8; k++ {
295 b := uint16(bs[k])
296
297 if b > idx[j] {
298 continue
299 }
300
301 ps[j][idx[j]] = ps[j][b]
302 ps[j][b] = 1
303
304
305 ps[j][b] ^= uint32((-(signs[j] & 1)) & (1 | (common.Q - 1)))
306 signs[j] >>= 1
307
308 idx[j]++
309 if idx[j] == common.N {
310 continue PolyLoop
311 }
312 }
313 }
314
315 done = false
316 }
317
318 if done {
319 break
320 }
321
322 perm.Permute()
323 stateOffset = 0
324 }
325 }
326
327
328
329
330 func PolyDeriveUniformBall(p *common.Poly, seed *[32]byte) {
331 var buf [136]byte
332
333 h := sha3.NewShake256()
334 _, _ = h.Write(seed[:])
335 _, _ = h.Read(buf[:])
336
337
338
339
340 signs := binary.LittleEndian.Uint64(buf[:])
341 bufOff := 8
342
343 *p = common.Poly{}
344 for i := uint16(common.N - Tau); i < common.N; i++ {
345 var b uint16
346
347
348
349 for {
350 if bufOff >= 136 {
351 _, _ = h.Read(buf[:])
352 bufOff = 0
353 }
354
355 b = uint16(buf[bufOff])
356 bufOff++
357
358 if b <= i {
359 break
360 }
361 }
362
363 p[i] = p[b]
364 p[b] = 1
365
366
367 p[b] ^= uint32((-(signs & 1)) & (1 | (common.Q - 1)))
368 signs >>= 1
369 }
370 }
371
View as plain text