...
1 package common
2
3 import (
4 "encoding/binary"
5
6 "github.com/cloudflare/circl/internal/sha3"
7 "github.com/cloudflare/circl/simd/keccakf1600"
8 )
9
10
11
12 var DeriveX4Available = keccakf1600.IsEnabledX4()
13
14
15
16
17 func (p *Poly) DeriveNoise(seed []byte, nonce uint8, eta int) {
18 switch eta {
19 case 2:
20 p.DeriveNoise2(seed, nonce)
21 case 3:
22 p.DeriveNoise3(seed, nonce)
23 default:
24 panic("unsupported eta")
25 }
26 }
27
28
29
30
31 func (p *Poly) DeriveNoise3(seed []byte, nonce uint8) {
32 keySuffix := [1]byte{nonce}
33 h := sha3.NewShake256()
34 _, _ = h.Write(seed[:])
35 _, _ = h.Write(keySuffix[:])
36
37
38
39
40
41
42
43 var buf [192 + 2]byte
44 _, _ = h.Read(buf[:192])
45
46 for i := 0; i < 32; i++ {
47
48 t := binary.LittleEndian.Uint64(buf[6*i:])
49
50 d := t & 0x249249249249
51 d += (t >> 1) & 0x249249249249
52 d += (t >> 2) & 0x249249249249
53
54 for j := 0; j < 8; j++ {
55 a := int16(d) & 0x7
56 d >>= 3
57 b := int16(d) & 0x7
58 d >>= 3
59 p[8*i+j] = a - b
60 }
61 }
62 }
63
64
65
66
67 func (p *Poly) DeriveNoise2(seed []byte, nonce uint8) {
68 keySuffix := [1]byte{nonce}
69 h := sha3.NewShake256()
70 _, _ = h.Write(seed[:])
71 _, _ = h.Write(keySuffix[:])
72
73
74
75
76
77 var buf [128]byte
78 _, _ = h.Read(buf[:])
79
80 for i := 0; i < 16; i++ {
81
82 t := binary.LittleEndian.Uint64(buf[8*i:])
83
84 d := t & 0x5555555555555555
85 d += (t >> 1) & 0x5555555555555555
86
87 for j := 0; j < 16; j++ {
88 a := int16(d) & 0x3
89 d >>= 2
90 b := int16(d) & 0x3
91 d >>= 2
92 p[16*i+j] = a - b
93 }
94 }
95 }
96
97
98
99
100
101 func PolyDeriveUniformX4(ps [4]*Poly, seed *[32]byte, xs, ys [4]uint8) {
102 var perm keccakf1600.StateX4
103 state := perm.Initialize(false)
104
105
106 for i := 0; i < 4; i++ {
107 v := binary.LittleEndian.Uint64(seed[8*i : 8*(i+1)])
108 for j := 0; j < 4; j++ {
109 state[i*4+j] = v
110 }
111 }
112
113
114
115
116 for j := 0; j < 4; j++ {
117 state[4*4+j] = uint64(xs[j]) | (uint64(ys[j]) << 8) | (0x1f << 16)
118 state[20*4+j] = 0x80 << 56
119 }
120
121 var idx [4]int
122 for j := 0; j < 4; j++ {
123 if ps[j] == nil {
124 idx[j] = N
125 }
126 }
127
128 done := false
129 for !done {
130
131
132 perm.Permute()
133
134 done = true
135
136 PolyLoop:
137 for j := 0; j < 4; j++ {
138 if idx[j] == N {
139 continue
140 }
141 for i := 0; i < 7; i++ {
142 var t [16]uint16
143
144 v1 := state[i*3*4+j]
145 v2 := state[(i*3+1)*4+j]
146 v3 := state[(i*3+2)*4+j]
147
148 t[0] = uint16(v1) & 0xfff
149 t[1] = uint16(v1>>12) & 0xfff
150 t[2] = uint16(v1>>24) & 0xfff
151 t[3] = uint16(v1>>36) & 0xfff
152 t[4] = uint16(v1>>48) & 0xfff
153 t[5] = uint16((v1>>60)|(v2<<4)) & 0xfff
154
155 t[6] = uint16(v2>>8) & 0xfff
156 t[7] = uint16(v2>>20) & 0xfff
157 t[8] = uint16(v2>>32) & 0xfff
158 t[9] = uint16(v2>>44) & 0xfff
159 t[10] = uint16((v2>>56)|(v3<<8)) & 0xfff
160
161 t[11] = uint16(v3>>4) & 0xfff
162 t[12] = uint16(v3>>16) & 0xfff
163 t[13] = uint16(v3>>28) & 0xfff
164 t[14] = uint16(v3>>40) & 0xfff
165 t[15] = uint16(v3>>52) & 0xfff
166
167 for k := 0; k < 16; k++ {
168 if t[k] < uint16(Q) {
169 ps[j][idx[j]] = int16(t[k])
170 idx[j]++
171 if idx[j] == N {
172 continue PolyLoop
173 }
174 }
175 }
176 }
177
178 done = false
179 }
180 }
181
182 for i := 0; i < 4; i++ {
183 if ps[i] != nil {
184 ps[i].Tangle()
185 }
186 }
187 }
188
189
190
191
192 func (p *Poly) DeriveUniform(seed *[32]byte, x, y uint8) {
193 var seedSuffix [2]byte
194 var buf [168]byte
195
196 seedSuffix[0] = x
197 seedSuffix[1] = y
198
199 h := sha3.NewShake128()
200 _, _ = h.Write(seed[:])
201 _, _ = h.Write(seedSuffix[:])
202
203 i := 0
204 for {
205 _, _ = h.Read(buf[:])
206
207 for j := 0; j < 168; j += 3 {
208 t1 := (uint16(buf[j]) | (uint16(buf[j+1]) << 8)) & 0xfff
209 t2 := (uint16(buf[j+1]>>4) | (uint16(buf[j+2]) << 4)) & 0xfff
210
211 if t1 < uint16(Q) {
212 p[i] = int16(t1)
213 i++
214
215 if i == N {
216 break
217 }
218 }
219
220 if t2 < uint16(Q) {
221 p[i] = int16(t2)
222 i++
223
224 if i == N {
225 break
226 }
227 }
228 }
229
230 if i == N {
231 break
232 }
233 }
234
235 p.Tangle()
236 }
237
View as plain text