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