Per FIPS 203 (https://csrc.nist.gov/pubs/fips/203/final), the order of return values should be sharedKey, ciphertext. This commit simply swaps those return values and updates any consumers of the Encapsulate() method to respect the new order.
Fixes #70950
Change-Id: I2a0d605e3baf7fe69510d60d3d35bbac18f883c9
Reviewed-on: https://go-review.googlesource.com/c/go/+/638376
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Austin Clements <austin@google.com>
Auto-Submit: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
dk := &DecapsulationKey768{}
kemKeyGen(dk, d, z)
ek := dk.EncapsulationKey()
- c, Ke := ek.EncapsulateInternal(m)
+ Ke, c := ek.EncapsulateInternal(m)
Kd, err := dk.Decapsulate(c)
if err != nil {
return err
// the first operational use (if not exported before the first use)."
func kemPCT1024(dk *DecapsulationKey1024) error {
ek := dk.EncapsulationKey()
- c, K := ek.Encapsulate()
+ K, c := ek.Encapsulate()
K1, err := dk.Decapsulate(c)
if err != nil {
return err
// encapsulation key, drawing random bytes from a DRBG.
//
// The shared key must be kept secret.
-func (ek *EncapsulationKey1024) Encapsulate() (ciphertext, sharedKey []byte) {
+func (ek *EncapsulationKey1024) Encapsulate() (sharedKey, ciphertext []byte) {
// The actual logic is in a separate function to outline this allocation.
var cc [CiphertextSize1024]byte
return ek.encapsulate(&cc)
}
-func (ek *EncapsulationKey1024) encapsulate(cc *[CiphertextSize1024]byte) (ciphertext, sharedKey []byte) {
+func (ek *EncapsulationKey1024) encapsulate(cc *[CiphertextSize1024]byte) (sharedKey, ciphertext []byte) {
var m [messageSize]byte
drbg.Read(m[:])
// Note that the modulus check (step 2 of the encapsulation key check from
// EncapsulateInternal is a derandomized version of Encapsulate, exclusively for
// use in tests.
-func (ek *EncapsulationKey1024) EncapsulateInternal(m *[32]byte) (ciphertext, sharedKey []byte) {
+func (ek *EncapsulationKey1024) EncapsulateInternal(m *[32]byte) (sharedKey, ciphertext []byte) {
cc := &[CiphertextSize1024]byte{}
return kemEncaps1024(cc, ek, m)
}
// kemEncaps1024 generates a shared key and an associated ciphertext.
//
// It implements ML-KEM.Encaps_internal according to FIPS 203, Algorithm 17.
-func kemEncaps1024(cc *[CiphertextSize1024]byte, ek *EncapsulationKey1024, m *[messageSize]byte) (c, K []byte) {
+func kemEncaps1024(cc *[CiphertextSize1024]byte, ek *EncapsulationKey1024, m *[messageSize]byte) (K, c []byte) {
g := sha3.New512()
g.Write(m[:])
g.Write(ek.h[:])
G := g.Sum(nil)
K, r := G[:SharedKeySize], G[SharedKeySize:]
c = pkeEncrypt1024(cc, &ek.encryptionKey1024, m, r)
- return c, K
+ return K, c
}
// NewEncapsulationKey1024 parses an encapsulation key from its encoded form.
// the first operational use (if not exported before the first use)."
func kemPCT(dk *DecapsulationKey768) error {
ek := dk.EncapsulationKey()
- c, K := ek.Encapsulate()
+ K, c := ek.Encapsulate()
K1, err := dk.Decapsulate(c)
if err != nil {
return err
// encapsulation key, drawing random bytes from a DRBG.
//
// The shared key must be kept secret.
-func (ek *EncapsulationKey768) Encapsulate() (ciphertext, sharedKey []byte) {
+func (ek *EncapsulationKey768) Encapsulate() (sharedKey, ciphertext []byte) {
// The actual logic is in a separate function to outline this allocation.
var cc [CiphertextSize768]byte
return ek.encapsulate(&cc)
}
-func (ek *EncapsulationKey768) encapsulate(cc *[CiphertextSize768]byte) (ciphertext, sharedKey []byte) {
+func (ek *EncapsulationKey768) encapsulate(cc *[CiphertextSize768]byte) (sharedKey, ciphertext []byte) {
var m [messageSize]byte
drbg.Read(m[:])
// Note that the modulus check (step 2 of the encapsulation key check from
// EncapsulateInternal is a derandomized version of Encapsulate, exclusively for
// use in tests.
-func (ek *EncapsulationKey768) EncapsulateInternal(m *[32]byte) (ciphertext, sharedKey []byte) {
+func (ek *EncapsulationKey768) EncapsulateInternal(m *[32]byte) (sharedKey, ciphertext []byte) {
cc := &[CiphertextSize768]byte{}
return kemEncaps(cc, ek, m)
}
// kemEncaps generates a shared key and an associated ciphertext.
//
// It implements ML-KEM.Encaps_internal according to FIPS 203, Algorithm 17.
-func kemEncaps(cc *[CiphertextSize768]byte, ek *EncapsulationKey768, m *[messageSize]byte) (c, K []byte) {
+func kemEncaps(cc *[CiphertextSize768]byte, ek *EncapsulationKey768, m *[messageSize]byte) (K, c []byte) {
g := sha3.New512()
g.Write(m[:])
g.Write(ek.h[:])
G := g.Sum(nil)
K, r := G[:SharedKeySize], G[SharedKeySize:]
c = pkeEncrypt(cc, &ek.encryptionKey, m, r)
- return c, K
+ return K, c
}
// NewEncapsulationKey768 parses an encapsulation key from its encoded form.
// encapsulation key, drawing random bytes from crypto/rand.
//
// The shared key must be kept secret.
-func (ek *EncapsulationKey1024) Encapsulate() (ciphertext, sharedKey []byte) {
+func (ek *EncapsulationKey1024) Encapsulate() (sharedKey, ciphertext []byte) {
return ek.key.Encapsulate()
}
// encapsulation key, drawing random bytes from crypto/rand.
//
// The shared key must be kept secret.
-func (ek *EncapsulationKey768) Encapsulate() (ciphertext, sharedKey []byte) {
+func (ek *EncapsulationKey768) Encapsulate() (sharedKey, ciphertext []byte) {
return ek.key.Encapsulate()
}
t.Fatal(err)
}
ek := dk.EncapsulationKey()
- c, Ke := ek.Encapsulate()
+ Ke, c := ek.Encapsulate()
Kd, err := dk.Decapsulate(c)
if err != nil {
t.Fatal(err)
if !bytes.Equal(dk.Bytes(), dk1.Bytes()) {
t.Fail()
}
- c1, Ke1 := ek1.Encapsulate()
+ Ke1, c1 := ek1.Encapsulate()
Kd1, err := dk1.Decapsulate(c1)
if err != nil {
t.Fatal(err)
t.Fail()
}
- c2, Ke2 := dk.EncapsulationKey().Encapsulate()
+ Ke2, c2 := dk.EncapsulationKey().Encapsulate()
if bytes.Equal(c, c2) {
t.Fail()
}
}
ek := dk.EncapsulationKey()
ekBytes := dk.EncapsulationKey().Bytes()
- c, _ := ek.Encapsulate()
+ _, c := ek.Encapsulate()
for i := 0; i < len(dkBytes)-1; i++ {
if _, err := newDecapsulationKey(dkBytes[:i]); err == nil {
o.Write(ek.Bytes())
s.Read(msg[:])
- ct, k := ek.key.EncapsulateInternal(&msg)
+ k, ct := ek.key.EncapsulateInternal(&msg)
o.Write(ct)
o.Write(k)
if err != nil {
b.Fatal(err)
}
- c, K := ek.key.EncapsulateInternal(&m)
+ K, c := ek.key.EncapsulateInternal(&m)
sink ^= c[0] ^ K[0]
}
}
b.Fatal(err)
}
ek := dk.EncapsulationKey()
- c, _ := ek.Encapsulate()
+ _, c := ek.Encapsulate()
b.ResetTimer()
for i := 0; i < b.N; i++ {
K, _ := dk.Decapsulate(c)
}
ek := dk.EncapsulationKey()
ekBytes := ek.Bytes()
- c, _ := ek.Encapsulate()
+ _, c := ek.Encapsulate()
if err != nil {
b.Fatal(err)
}
if err != nil {
b.Fatal(err)
}
- cS, Ks := ek.Encapsulate()
+ Ks, cS := ek.Encapsulate()
if err != nil {
b.Fatal(err)
}
c.sendAlert(alertIllegalParameter)
return errors.New("tls: invalid X25519MLKEM768 client key share")
}
- ciphertext, mlkemSharedSecret := k.Encapsulate()
+ mlkemSharedSecret, ciphertext := k.Encapsulate()
// draft-kwiatkowski-tls-ecdhe-mlkem-02, Section 3.1.3: "For
// X25519MLKEM768, the shared secret is the concatenation of the ML-KEM
// shared secret and the X25519 shared secret. The shared secret is 64