1
2
3 package mlkem
4
5 import (
6 "bytes"
7 "crypto/internal/fips140"
8 "crypto/internal/fips140/drbg"
9 "crypto/internal/fips140/sha3"
10 "crypto/internal/fips140/subtle"
11 "errors"
12 )
13
14
15
16 type DecapsulationKey1024 struct {
17 d [32]byte
18 z [32]byte
19
20 ρ [32]byte
21 h [32]byte
22
23 encryptionKey1024
24 decryptionKey1024
25 }
26
27
28
29
30 func (dk *DecapsulationKey1024) Bytes() []byte {
31 var b [SeedSize]byte
32 copy(b[:], dk.d[:])
33 copy(b[32:], dk.z[:])
34 return b[:]
35 }
36
37
38
39
40
41
42 func TestingOnlyExpandedBytes1024(dk *DecapsulationKey1024) []byte {
43 b := make([]byte, 0, decapsulationKeySize1024)
44
45
46 for i := range dk.s {
47 b = polyByteEncode(b, dk.s[i])
48 }
49
50
51 for i := range dk.t {
52 b = polyByteEncode(b, dk.t[i])
53 }
54 b = append(b, dk.ρ[:]...)
55
56
57 b = append(b, dk.h[:]...)
58 b = append(b, dk.z[:]...)
59
60 return b
61 }
62
63
64
65 func (dk *DecapsulationKey1024) EncapsulationKey() *EncapsulationKey1024 {
66 return &EncapsulationKey1024{
67 ρ: dk.ρ,
68 h: dk.h,
69 encryptionKey1024: dk.encryptionKey1024,
70 }
71 }
72
73
74
75 type EncapsulationKey1024 struct {
76 ρ [32]byte
77 h [32]byte
78 encryptionKey1024
79 }
80
81
82 func (ek *EncapsulationKey1024) Bytes() []byte {
83
84 b := make([]byte, 0, EncapsulationKeySize1024)
85 return ek.bytes(b)
86 }
87
88 func (ek *EncapsulationKey1024) bytes(b []byte) []byte {
89 for i := range ek.t {
90 b = polyByteEncode(b, ek.t[i])
91 }
92 b = append(b, ek.ρ[:]...)
93 return b
94 }
95
96
97 type encryptionKey1024 struct {
98 t [k1024]nttElement
99 a [k1024 * k1024]nttElement
100 }
101
102
103 type decryptionKey1024 struct {
104 s [k1024]nttElement
105 }
106
107
108
109 func GenerateKey1024() (*DecapsulationKey1024, error) {
110
111 dk := &DecapsulationKey1024{}
112 return generateKey1024(dk)
113 }
114
115 func generateKey1024(dk *DecapsulationKey1024) (*DecapsulationKey1024, error) {
116 fipsSelfTest()
117 var d [32]byte
118 drbg.Read(d[:])
119 var z [32]byte
120 drbg.Read(z[:])
121 kemKeyGen1024(dk, &d, &z)
122 fips140.PCT("ML-KEM PCT", func() error { return kemPCT1024(dk) })
123 fips140.RecordApproved()
124 return dk, nil
125 }
126
127
128
129 func GenerateKeyInternal1024(d, z *[32]byte) *DecapsulationKey1024 {
130 fipsSelfTest()
131 dk := &DecapsulationKey1024{}
132 kemKeyGen1024(dk, d, z)
133 return dk
134 }
135
136
137
138 func NewDecapsulationKey1024(seed []byte) (*DecapsulationKey1024, error) {
139
140 dk := &DecapsulationKey1024{}
141 return newKeyFromSeed1024(dk, seed)
142 }
143
144 func newKeyFromSeed1024(dk *DecapsulationKey1024, seed []byte) (*DecapsulationKey1024, error) {
145 fipsSelfTest()
146 if len(seed) != SeedSize {
147 return nil, errors.New("mlkem: invalid seed length")
148 }
149 d := (*[32]byte)(seed[:32])
150 z := (*[32]byte)(seed[32:])
151 kemKeyGen1024(dk, d, z)
152 fips140.RecordApproved()
153 return dk, nil
154 }
155
156
157
158
159
160
161
162
163 func TestingOnlyNewDecapsulationKey1024(b []byte) (*DecapsulationKey1024, error) {
164 if len(b) != decapsulationKeySize1024 {
165 return nil, errors.New("mlkem: invalid NIST decapsulation key length")
166 }
167
168 dk := &DecapsulationKey1024{}
169 for i := range dk.s {
170 var err error
171 dk.s[i], err = polyByteDecode[nttElement](b[:encodingSize12])
172 if err != nil {
173 return nil, errors.New("mlkem: invalid secret key encoding")
174 }
175 b = b[encodingSize12:]
176 }
177
178 ek, err := NewEncapsulationKey1024(b[:EncapsulationKeySize1024])
179 if err != nil {
180 return nil, err
181 }
182 dk.ρ = ek.ρ
183 dk.h = ek.h
184 dk.encryptionKey1024 = ek.encryptionKey1024
185 b = b[EncapsulationKeySize1024:]
186
187 if !bytes.Equal(dk.h[:], b[:32]) {
188 return nil, errors.New("mlkem: inconsistent H(ek) in encoded bytes")
189 }
190 b = b[32:]
191
192 copy(dk.z[:], b)
193
194
195
196
197
198 drbg.Read(dk.d[:])
199
200 return dk, nil
201 }
202
203
204
205
206
207
208 func kemKeyGen1024(dk *DecapsulationKey1024, d, z *[32]byte) {
209 dk.d = *d
210 dk.z = *z
211
212 g := sha3.New512()
213 g.Write(d[:])
214 g.Write([]byte{k1024})
215 G := g.Sum(make([]byte, 0, 64))
216 ρ, σ := G[:32], G[32:]
217 dk.ρ = [32]byte(ρ)
218
219 A := &dk.a
220 for i := byte(0); i < k1024; i++ {
221 for j := byte(0); j < k1024; j++ {
222 A[i*k1024+j] = sampleNTT(ρ, j, i)
223 }
224 }
225
226 var N byte
227 s := &dk.s
228 for i := range s {
229 s[i] = ntt(samplePolyCBD(σ, N))
230 N++
231 }
232 e := make([]nttElement, k1024)
233 for i := range e {
234 e[i] = ntt(samplePolyCBD(σ, N))
235 N++
236 }
237
238 t := &dk.t
239 for i := range t {
240 t[i] = e[i]
241 for j := range s {
242 t[i] = polyAdd(t[i], nttMul(A[i*k1024+j], s[j]))
243 }
244 }
245
246 H := sha3.New256()
247 ek := dk.EncapsulationKey().Bytes()
248 H.Write(ek)
249 H.Sum(dk.h[:0])
250 }
251
252
253
254
255
256
257
258
259
260 func kemPCT1024(dk *DecapsulationKey1024) error {
261 ek := dk.EncapsulationKey()
262 K, c := ek.Encapsulate()
263 K1, err := dk.Decapsulate(c)
264 if err != nil {
265 return err
266 }
267 if subtle.ConstantTimeCompare(K, K1) != 1 {
268 return errors.New("mlkem: PCT failed")
269 }
270 return nil
271 }
272
273
274
275
276
277 func (ek *EncapsulationKey1024) Encapsulate() (sharedKey, ciphertext []byte) {
278
279 var cc [CiphertextSize1024]byte
280 return ek.encapsulate(&cc)
281 }
282
283 func (ek *EncapsulationKey1024) encapsulate(cc *[CiphertextSize1024]byte) (sharedKey, ciphertext []byte) {
284 fipsSelfTest()
285 var m [messageSize]byte
286 drbg.Read(m[:])
287
288
289 fips140.RecordApproved()
290 return kemEncaps1024(cc, ek, &m)
291 }
292
293
294
295 func (ek *EncapsulationKey1024) EncapsulateInternal(m *[32]byte) (sharedKey, ciphertext []byte) {
296 fipsSelfTest()
297 cc := &[CiphertextSize1024]byte{}
298 return kemEncaps1024(cc, ek, m)
299 }
300
301
302
303
304 func kemEncaps1024(cc *[CiphertextSize1024]byte, ek *EncapsulationKey1024, m *[messageSize]byte) (K, c []byte) {
305 g := sha3.New512()
306 g.Write(m[:])
307 g.Write(ek.h[:])
308 G := g.Sum(nil)
309 K, r := G[:SharedKeySize], G[SharedKeySize:]
310 c = pkeEncrypt1024(cc, &ek.encryptionKey1024, m, r)
311 return K, c
312 }
313
314
315
316 func NewEncapsulationKey1024(encapsulationKey []byte) (*EncapsulationKey1024, error) {
317
318 ek := &EncapsulationKey1024{}
319 return parseEK1024(ek, encapsulationKey)
320 }
321
322
323
324
325
326 func parseEK1024(ek *EncapsulationKey1024, ekPKE []byte) (*EncapsulationKey1024, error) {
327 if len(ekPKE) != EncapsulationKeySize1024 {
328 return nil, errors.New("mlkem: invalid encapsulation key length")
329 }
330
331 h := sha3.New256()
332 h.Write(ekPKE)
333 h.Sum(ek.h[:0])
334
335 for i := range ek.t {
336 var err error
337 ek.t[i], err = polyByteDecode[nttElement](ekPKE[:encodingSize12])
338 if err != nil {
339 return nil, err
340 }
341 ekPKE = ekPKE[encodingSize12:]
342 }
343 copy(ek.ρ[:], ekPKE)
344
345 for i := byte(0); i < k1024; i++ {
346 for j := byte(0); j < k1024; j++ {
347 ek.a[i*k1024+j] = sampleNTT(ek.ρ[:], j, i)
348 }
349 }
350
351 return ek, nil
352 }
353
354
355
356
357
358 func pkeEncrypt1024(cc *[CiphertextSize1024]byte, ex *encryptionKey1024, m *[messageSize]byte, rnd []byte) []byte {
359 var N byte
360 r, e1 := make([]nttElement, k1024), make([]ringElement, k1024)
361 for i := range r {
362 r[i] = ntt(samplePolyCBD(rnd, N))
363 N++
364 }
365 for i := range e1 {
366 e1[i] = samplePolyCBD(rnd, N)
367 N++
368 }
369 e2 := samplePolyCBD(rnd, N)
370
371 u := make([]ringElement, k1024)
372 for i := range u {
373 var uHat nttElement
374 for j := range r {
375
376 uHat = polyAdd(uHat, nttMul(ex.a[j*k1024+i], r[j]))
377 }
378 u[i] = polyAdd(e1[i], inverseNTT(uHat))
379 }
380
381 μ := ringDecodeAndDecompress1(m)
382
383 var vNTT nttElement
384 for i := range ex.t {
385 vNTT = polyAdd(vNTT, nttMul(ex.t[i], r[i]))
386 }
387 v := polyAdd(polyAdd(inverseNTT(vNTT), e2), μ)
388
389 c := cc[:0]
390 for _, f := range u {
391 c = ringCompressAndEncode11(c, f)
392 }
393 c = ringCompressAndEncode5(c, v)
394
395 return c
396 }
397
398
399
400
401
402 func (dk *DecapsulationKey1024) Decapsulate(ciphertext []byte) (sharedKey []byte, err error) {
403 fipsSelfTest()
404 if len(ciphertext) != CiphertextSize1024 {
405 return nil, errors.New("mlkem: invalid ciphertext length")
406 }
407 c := (*[CiphertextSize1024]byte)(ciphertext)
408
409
410
411 return kemDecaps1024(dk, c), nil
412 }
413
414
415
416
417 func kemDecaps1024(dk *DecapsulationKey1024, c *[CiphertextSize1024]byte) (K []byte) {
418 fips140.RecordApproved()
419 m := pkeDecrypt1024(&dk.decryptionKey1024, c)
420 g := sha3.New512()
421 g.Write(m[:])
422 g.Write(dk.h[:])
423 G := g.Sum(make([]byte, 0, 64))
424 Kprime, r := G[:SharedKeySize], G[SharedKeySize:]
425 J := sha3.NewShake256()
426 J.Write(dk.z[:])
427 J.Write(c[:])
428 Kout := make([]byte, SharedKeySize)
429 J.Read(Kout)
430 var cc [CiphertextSize1024]byte
431 c1 := pkeEncrypt1024(&cc, &dk.encryptionKey1024, (*[32]byte)(m), r)
432
433 subtle.ConstantTimeCopy(subtle.ConstantTimeCompare(c[:], c1), Kout, Kprime)
434 return Kout
435 }
436
437
438
439
440
441 func pkeDecrypt1024(dx *decryptionKey1024, c *[CiphertextSize1024]byte) []byte {
442 u := make([]ringElement, k1024)
443 for i := range u {
444 b := (*[encodingSize11]byte)(c[encodingSize11*i : encodingSize11*(i+1)])
445 u[i] = ringDecodeAndDecompress11(b)
446 }
447
448 b := (*[encodingSize5]byte)(c[encodingSize11*k1024:])
449 v := ringDecodeAndDecompress5(b)
450
451 var mask nttElement
452 for i := range dx.s {
453 mask = polyAdd(mask, nttMul(dx.s[i], ntt(u[i])))
454 }
455 w := polySub(v, inverseNTT(mask))
456
457 return ringCompressAndEncode1(nil, w)
458 }
459
View as plain text