fix: broken PSK session resumption

This commit is contained in:
Mingye Chen 2025-01-14 01:04:48 -07:00
parent 0114defe06
commit 3d730b9fb2
3 changed files with 51 additions and 35 deletions

View file

@ -14,7 +14,6 @@ import (
"github.com/andybalholm/brotli" "github.com/andybalholm/brotli"
"github.com/klauspost/compress/zstd" "github.com/klauspost/compress/zstd"
"github.com/refraction-networking/utls/internal/hpke" "github.com/refraction-networking/utls/internal/hpke"
"github.com/refraction-networking/utls/internal/mlkem768"
) )
// This function is called by (*clientHandshakeStateTLS13).readServerCertificate() // This function is called by (*clientHandshakeStateTLS13).readServerCertificate()
@ -292,40 +291,40 @@ func (c *Conn) makeClientHelloForApplyPreset() (*clientHelloMsg, *keySharePrivat
hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...) hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...)
} }
curveID := config.curvePreferences(maxVersion)[0] // curveID := config.curvePreferences(maxVersion)[0]
keyShareKeys = &keySharePrivateKeys{curveID: curveID} // keyShareKeys = &keySharePrivateKeys{curveID: curveID}
if curveID == x25519Kyber768Draft00 { // if curveID == x25519Kyber768Draft00 {
keyShareKeys.ecdhe, err = generateECDHEKey(config.rand(), X25519) // keyShareKeys.ecdhe, err = generateECDHEKey(config.rand(), X25519)
if err != nil { // if err != nil {
return nil, nil, nil, err // return nil, nil, nil, err
} // }
seed := make([]byte, mlkem768.SeedSize) // seed := make([]byte, mlkem768.SeedSize)
if _, err := io.ReadFull(config.rand(), seed); err != nil { // if _, err := io.ReadFull(config.rand(), seed); err != nil {
return nil, nil, nil, err // return nil, nil, nil, err
} // }
keyShareKeys.kyber, err = mlkem768.NewKeyFromSeed(seed) // keyShareKeys.kyber, err = mlkem768.NewKeyFromSeed(seed)
if err != nil { // if err != nil {
return nil, nil, nil, err // return nil, nil, nil, err
} // }
// For draft-tls-westerbaan-xyber768d00-03, we send both a hybrid // // For draft-tls-westerbaan-xyber768d00-03, we send both a hybrid
// and a standard X25519 key share, since most servers will only // // and a standard X25519 key share, since most servers will only
// support the latter. We reuse the same X25519 ephemeral key for // // support the latter. We reuse the same X25519 ephemeral key for
// both, as allowed by draft-ietf-tls-hybrid-design-09, Section 3.2. // // both, as allowed by draft-ietf-tls-hybrid-design-09, Section 3.2.
hello.keyShares = []keyShare{ // hello.keyShares = []keyShare{
{group: x25519Kyber768Draft00, data: append(keyShareKeys.ecdhe.PublicKey().Bytes(), // {group: x25519Kyber768Draft00, data: append(keyShareKeys.ecdhe.PublicKey().Bytes(),
keyShareKeys.kyber.EncapsulationKey()...)}, // keyShareKeys.kyber.EncapsulationKey()...)},
{group: X25519, data: keyShareKeys.ecdhe.PublicKey().Bytes()}, // {group: X25519, data: keyShareKeys.ecdhe.PublicKey().Bytes()},
} // }
} else { // } else {
if _, ok := curveForCurveID(curveID); !ok { // if _, ok := curveForCurveID(curveID); !ok {
return nil, nil, nil, errors.New("tls: CurvePreferences includes unsupported curve") // return nil, nil, nil, errors.New("tls: CurvePreferences includes unsupported curve")
} // }
keyShareKeys.ecdhe, err = generateECDHEKey(config.rand(), curveID) // keyShareKeys.ecdhe, err = generateECDHEKey(config.rand(), curveID)
if err != nil { // if err != nil {
return nil, nil, nil, err // return nil, nil, nil, err
} // }
hello.keyShares = []keyShare{{group: curveID, data: keyShareKeys.ecdhe.PublicKey().Bytes()}} // hello.keyShares = []keyShare{{group: curveID, data: keyShareKeys.ecdhe.PublicKey().Bytes()}}
} // }
} }
// [UTLS] We don't need this, since it is not ready yet // [UTLS] We don't need this, since it is not ready yet

View file

@ -2633,6 +2633,8 @@ func (uconn *UConn) ApplyPreset(p *ClientHelloSpec) error {
uconn.HandshakeState.Hello = privateHello.getPublicPtr() uconn.HandshakeState.Hello = privateHello.getPublicPtr()
if clientKeySharePrivate != nil { if clientKeySharePrivate != nil {
uconn.HandshakeState.State13.KeyShareKeys = clientKeySharePrivate.ToPublic() uconn.HandshakeState.State13.KeyShareKeys = clientKeySharePrivate.ToPublic()
} else {
uconn.HandshakeState.State13.KeyShareKeys = &KeySharePrivateKeys{}
} }
uconn.HandshakeState.State13.KeySharesParams = NewKeySharesParameters() uconn.HandshakeState.State13.KeySharesParams = NewKeySharesParameters()
hello := uconn.HandshakeState.Hello hello := uconn.HandshakeState.Hello

View file

@ -284,6 +284,21 @@ func (e *UtlsPreSharedKeyExtension) PatchBuiltHello(hello *PubClientHelloMsg) er
if err := private.updateBinders(pskBinders); err != nil { if err := private.updateBinders(pskBinders); err != nil {
return err return err
} }
// copied from handshake_messages.go in 1.22
lenWithoutBinders := len(helloBytes)
b := cryptobyte.NewFixedBuilder(private.original[:lenWithoutBinders])
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
for _, binder := range private.pskBinders {
b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
b.AddBytes(binder)
})
}
})
if out, err := b.Bytes(); err != nil || len(out) != len(private.original) {
return errors.New("tls: internal error: failed to update binders")
}
//--- mirror loadSession() end ---// //--- mirror loadSession() end ---//
e.Binders = pskBinders e.Binders = pskBinders