Skip to content

Commit 66c4bb7

Browse files
committed
fixup and add tests
1 parent d89de55 commit 66c4bb7

File tree

2 files changed

+281
-22
lines changed

2 files changed

+281
-22
lines changed

cng/mlkem.go

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,36 @@ const (
2424
// ciphertextSizeMLKEM768 is the size of a ciphertext produced by ML-KEM-768.
2525
ciphertextSizeMLKEM768 = 1088
2626

27-
// encapsulationKeySizeMLKEM768 is the size of an ML-KEM-768 encapsulation key.
27+
// encapsulationKeySizeMLKEM768 is the size of an ML-KEM-768 encapsulation key (raw key material).
2828
encapsulationKeySizeMLKEM768 = 1184
2929

30-
// decapsulationKeySizeMLKEM768 is the size of the ML-KEM-768 decapsulation key data
31-
// (Windows blob format, without header).
30+
// encapsulationKeyBlobSizeMLKEM768 is the size of the ML-KEM-768 encapsulation key blob
31+
// (Windows blob format, with header).
32+
encapsulationKeyBlobSizeMLKEM768 = 1204 // 12 + 8 ("768\0" in UTF-16) + 1184
33+
34+
// decapsulationKeySizeMLKEM768 is the size of the ML-KEM-768 decapsulation key data (raw key material).
3235
decapsulationKeySizeMLKEM768 = 2400
3336

37+
// decapsulationKeyBlobSizeMLKEM768 is the size of the ML-KEM-768 decapsulation key blob
38+
// (Windows blob format, with header).
39+
decapsulationKeyBlobSizeMLKEM768 = 2420 // 12 + 8 ("768\0" in UTF-16) + 2400
40+
3441
// ciphertextSizeMLKEM1024 is the size of a ciphertext produced by ML-KEM-1024.
3542
ciphertextSizeMLKEM1024 = 1568
3643

37-
// encapsulationKeySizeMLKEM1024 is the size of an ML-KEM-1024 encapsulation key.
44+
// encapsulationKeySizeMLKEM1024 is the size of an ML-KEM-1024 encapsulation key (raw key material).
3845
encapsulationKeySizeMLKEM1024 = 1568
3946

40-
// decapsulationKeySizeMLKEM1024 is the size of the ML-KEM-1024 decapsulation key data
41-
// (Windows blob format, without header).
47+
// encapsulationKeyBlobSizeMLKEM1024 is the size of the ML-KEM-1024 encapsulation key blob
48+
// (Windows blob format, with header).
49+
encapsulationKeyBlobSizeMLKEM1024 = 1590 // 12 + 10 ("1024\0" in UTF-16) + 1568
50+
51+
// decapsulationKeySizeMLKEM1024 is the size of the ML-KEM-1024 decapsulation key data (raw key material).
4252
decapsulationKeySizeMLKEM1024 = 3168
53+
54+
// decapsulationKeyBlobSizeMLKEM1024 is the size of the ML-KEM-1024 decapsulation key blob
55+
// (Windows blob format, with header).
56+
decapsulationKeyBlobSizeMLKEM1024 = 3190 // 12 + 10 ("1024\0" in UTF-16) + 3168
4357
)
4458

4559
// putUint32LE puts a uint32 in little-endian byte order.
@@ -177,7 +191,7 @@ func extractMLKEMKeyBytes(blob []byte) []byte {
177191

178192
// DecapsulationKeyMLKEM768 is the secret key used to decapsulate a shared key
179193
// from a ciphertext. It includes various precomputed values.
180-
type DecapsulationKeyMLKEM768 [seedSizeMLKEM]byte
194+
type DecapsulationKeyMLKEM768 [decapsulationKeyBlobSizeMLKEM768]byte
181195

182196
// GenerateKeyMLKEM768 generates a new decapsulation key, drawing random bytes from
183197
// the default crypto/rand source. The decapsulation key must be kept secret.
@@ -186,14 +200,16 @@ func GenerateKeyMLKEM768() (DecapsulationKeyMLKEM768, error) {
186200
if err != nil {
187201
return DecapsulationKeyMLKEM768{}, err
188202
}
189-
return DecapsulationKeyMLKEM768(blob), nil
203+
var dk DecapsulationKeyMLKEM768
204+
copy(dk[:], blob)
205+
return dk, nil
190206
}
191207

192208
// NewDecapsulationKeyMLKEM768 expands a decapsulation key from a 64-byte seed in the
193209
// "d || z" form. The seed must be uniformly random.
194210
func NewDecapsulationKeyMLKEM768(seed []byte) (DecapsulationKeyMLKEM768, error) {
195-
// Windows CNG implementation: we store the full private key blob, not just a seed
196-
// The input here is actually the full blob (returned by Bytes()), not a seed
211+
// The input is raw key bytes extracted from a blob (returned by Bytes())
212+
// We need to construct the full blob with header
197213
if len(seed) != decapsulationKeySizeMLKEM768 {
198214
return DecapsulationKeyMLKEM768{}, errors.New("mlkem: invalid decapsulation key size")
199215
}
@@ -202,7 +218,10 @@ func NewDecapsulationKeyMLKEM768(seed []byte) (DecapsulationKeyMLKEM768, error)
202218
if err != nil {
203219
return DecapsulationKeyMLKEM768{}, err
204220
}
205-
return DecapsulationKeyMLKEM768(blob), nil
221+
222+
var dk DecapsulationKeyMLKEM768
223+
copy(dk[:], blob)
224+
return dk, nil
206225
}
207226

208227
// Bytes returns the decapsulation key as a 64-byte seed in the "d || z" form.
@@ -273,12 +292,14 @@ func (dk DecapsulationKeyMLKEM768) EncapsulationKey() EncapsulationKeyMLKEM768 {
273292
}
274293

275294
runtime.KeepAlive(dk)
276-
return EncapsulationKeyMLKEM768(pubBlob)
295+
var ek EncapsulationKeyMLKEM768
296+
copy(ek[:], pubBlob)
297+
return ek
277298
}
278299

279300
// An EncapsulationKeyMLKEM768 is the public key used to produce ciphertexts to be
280301
// decapsulated by the corresponding DecapsulationKeyMLKEM768.
281-
type EncapsulationKeyMLKEM768 [encapsulationKeySizeMLKEM768]byte
302+
type EncapsulationKeyMLKEM768 [encapsulationKeyBlobSizeMLKEM768]byte
282303

283304
// NewEncapsulationKeyMLKEM768 parses an encapsulation key from its encoded form. If
284305
// the encapsulation key is not valid, NewEncapsulationKeyMLKEM768 returns an error.
@@ -291,7 +312,10 @@ func NewEncapsulationKeyMLKEM768(encapsulationKey []byte) (EncapsulationKeyMLKEM
291312
if err != nil {
292313
return EncapsulationKeyMLKEM768{}, err
293314
}
294-
return EncapsulationKeyMLKEM768(blob), nil
315+
316+
var ek EncapsulationKeyMLKEM768
317+
copy(ek[:], blob)
318+
return ek, nil
295319
}
296320

297321
// Bytes returns the encapsulation key as a byte slice.
@@ -336,7 +360,7 @@ func (ek EncapsulationKeyMLKEM768) Encapsulate() (sharedKey, ciphertext []byte)
336360

337361
// DecapsulationKeyMLKEM1024 is the secret key used to decapsulate a shared key
338362
// from a ciphertext. It includes various precomputed values.
339-
type DecapsulationKeyMLKEM1024 [seedSizeMLKEM]byte
363+
type DecapsulationKeyMLKEM1024 [decapsulationKeyBlobSizeMLKEM1024]byte
340364

341365
// GenerateKeyMLKEM1024 generates a new decapsulation key, drawing random bytes from
342366
// the default crypto/rand source. The decapsulation key must be kept secret.
@@ -345,14 +369,16 @@ func GenerateKeyMLKEM1024() (DecapsulationKeyMLKEM1024, error) {
345369
if err != nil {
346370
return DecapsulationKeyMLKEM1024{}, err
347371
}
348-
return DecapsulationKeyMLKEM1024(blob), nil
372+
var dk DecapsulationKeyMLKEM1024
373+
copy(dk[:], blob)
374+
return dk, nil
349375
}
350376

351377
// NewDecapsulationKeyMLKEM1024 expands a decapsulation key from a 64-byte seed in the
352378
// "d || z" form. The seed must be uniformly random.
353379
func NewDecapsulationKeyMLKEM1024(seed []byte) (DecapsulationKeyMLKEM1024, error) {
354-
// Windows CNG implementation: we store the full private key blob, not just a seed
355-
// The input here is actually the full blob (returned by Bytes()), not a seed
380+
// The input is raw key bytes extracted from a blob (returned by Bytes())
381+
// We need to construct the full blob with header
356382
if len(seed) != decapsulationKeySizeMLKEM1024 {
357383
return DecapsulationKeyMLKEM1024{}, errors.New("mlkem: invalid decapsulation key size")
358384
}
@@ -361,7 +387,10 @@ func NewDecapsulationKeyMLKEM1024(seed []byte) (DecapsulationKeyMLKEM1024, error
361387
if err != nil {
362388
return DecapsulationKeyMLKEM1024{}, err
363389
}
364-
return DecapsulationKeyMLKEM1024(blob), nil
390+
391+
var dk DecapsulationKeyMLKEM1024
392+
copy(dk[:], blob)
393+
return dk, nil
365394
}
366395

367396
// Bytes returns the decapsulation key as a 64-byte seed in the "d || z" form.
@@ -432,12 +461,14 @@ func (dk DecapsulationKeyMLKEM1024) EncapsulationKey() EncapsulationKeyMLKEM1024
432461
}
433462

434463
runtime.KeepAlive(dk)
435-
return EncapsulationKeyMLKEM1024(pubBlob)
464+
var ek EncapsulationKeyMLKEM1024
465+
copy(ek[:], pubBlob)
466+
return ek
436467
}
437468

438469
// An EncapsulationKeyMLKEM1024 is the public key used to produce ciphertexts to be
439470
// decapsulated by the corresponding DecapsulationKeyMLKEM1024.
440-
type EncapsulationKeyMLKEM1024 [encapsulationKeySizeMLKEM1024]byte
471+
type EncapsulationKeyMLKEM1024 [encapsulationKeyBlobSizeMLKEM1024]byte
441472

442473
// NewEncapsulationKeyMLKEM1024 parses an encapsulation key from its encoded form. If
443474
// the encapsulation key is not valid, NewEncapsulationKeyMLKEM1024 returns an error.
@@ -450,7 +481,10 @@ func NewEncapsulationKeyMLKEM1024(encapsulationKey []byte) (EncapsulationKeyMLKE
450481
if err != nil {
451482
return EncapsulationKeyMLKEM1024{}, err
452483
}
453-
return EncapsulationKeyMLKEM1024(blob), nil
484+
485+
var ek EncapsulationKeyMLKEM1024
486+
copy(ek[:], blob)
487+
return ek, nil
454488
}
455489

456490
// Bytes returns the encapsulation key as a byte slice.

0 commit comments

Comments
 (0)