mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-22 14:38:34 +00:00
Empty hash11 for "native"; Verify NFS paddings; Fix 1-RTT's peerRandom
https://github.com/XTLS/Xray-core/pull/4952#issuecomment-3213837443
This commit is contained in:
parent
38cc306c95
commit
b33555cc0a
@ -59,13 +59,13 @@ func (i *ClientInstance) Init(nfsEKeyBytes, xorPKeyBytes []byte, xorMode, minute
|
|||||||
if i.nfsEKey, err = mlkem.NewEncapsulationKey768(nfsEKeyBytes); err != nil {
|
if i.nfsEKey, err = mlkem.NewEncapsulationKey768(nfsEKeyBytes); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
hash32 := sha3.Sum256(nfsEKeyBytes)
|
|
||||||
copy(i.hash11[:], hash32[:])
|
|
||||||
if xorMode > 0 {
|
if xorMode > 0 {
|
||||||
i.xorMode = xorMode
|
i.xorMode = xorMode
|
||||||
if i.xorPKey, err = ecdh.X25519().NewPublicKey(xorPKeyBytes); err != nil {
|
if i.xorPKey, err = ecdh.X25519().NewPublicKey(xorPKeyBytes); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
hash32 := sha3.Sum256(nfsEKeyBytes)
|
||||||
|
copy(i.hash11[:], hash32[:])
|
||||||
}
|
}
|
||||||
i.minutes = time.Duration(minutes) * time.Minute
|
i.minutes = time.Duration(minutes) * time.Minute
|
||||||
return
|
return
|
||||||
@ -115,7 +115,7 @@ func (i *ClientInstance) Handshake(conn net.Conn) (*ClientConn, error) {
|
|||||||
}
|
}
|
||||||
// client can send more NFS AEAD paddings / messages if needed
|
// client can send more NFS AEAD paddings / messages if needed
|
||||||
|
|
||||||
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before server hello
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn, nil, nil) // allow paddings before server hello
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -198,9 +198,9 @@ func (c *ClientConn) Read(b []byte) (int, error) {
|
|||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
if c.peerAEAD == nil {
|
if c.peerAEAD == nil {
|
||||||
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before random hello
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn, nil, nil) // allow paddings before random hello
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if c.instance != nil && strings.HasPrefix(err.Error(), "invalid header: ") { // 0-RTT's 0-RTT
|
if c.instance != nil && strings.HasPrefix(err.Error(), "invalid header: ") { // 0-RTT
|
||||||
c.instance.Lock()
|
c.instance.Lock()
|
||||||
if bytes.Equal(c.ticket, c.instance.ticket) {
|
if bytes.Equal(c.ticket, c.instance.ticket) {
|
||||||
c.instance.expire = time.Now() // expired
|
c.instance.expire = time.Now() // expired
|
||||||
|
@ -61,14 +61,21 @@ func ReadAndDecodeHeader(conn net.Conn) (h []byte, t byte, l int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadAndDiscardPaddings(conn net.Conn) (h []byte, t byte, l int, err error) {
|
func ReadAndDiscardPaddings(conn net.Conn, aead cipher.AEAD, nonce []byte) (h []byte, t byte, l int, err error) {
|
||||||
for {
|
for {
|
||||||
if h, t, l, err = ReadAndDecodeHeader(conn); err != nil || t != 23 {
|
if h, t, l, err = ReadAndDecodeHeader(conn); err != nil || t != 23 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err = io.ReadFull(conn, make([]byte, l)); err != nil {
|
padding := make([]byte, l)
|
||||||
|
if _, err = io.ReadFull(conn, padding); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if aead != nil {
|
||||||
|
if _, err := aead.Open(nil, nonce, padding, h); err != nil {
|
||||||
|
return h, t, l, err
|
||||||
|
}
|
||||||
|
IncreaseNonce(nonce)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,13 +56,13 @@ func (i *ServerInstance) Init(nfsDKeySeed, xorSKeyBytes []byte, xorMode, minutes
|
|||||||
if i.nfsDKey, err = mlkem.NewDecapsulationKey768(nfsDKeySeed); err != nil {
|
if i.nfsDKey, err = mlkem.NewDecapsulationKey768(nfsDKeySeed); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
hash32 := sha3.Sum256(i.nfsDKey.EncapsulationKey().Bytes())
|
|
||||||
copy(i.hash11[:], hash32[:])
|
|
||||||
if xorMode > 0 {
|
if xorMode > 0 {
|
||||||
i.xorMode = xorMode
|
i.xorMode = xorMode
|
||||||
if i.xorSKey, err = ecdh.X25519().NewPrivateKey(xorSKeyBytes); err != nil {
|
if i.xorSKey, err = ecdh.X25519().NewPrivateKey(xorSKeyBytes); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
hash32 := sha3.Sum256(i.nfsDKey.EncapsulationKey().Bytes())
|
||||||
|
copy(i.hash11[:], hash32[:])
|
||||||
}
|
}
|
||||||
if minutes > 0 {
|
if minutes > 0 {
|
||||||
i.minutes = time.Duration(minutes) * time.Minute
|
i.minutes = time.Duration(minutes) * time.Minute
|
||||||
@ -107,7 +107,7 @@ func (i *ServerInstance) Handshake(conn net.Conn) (*ServerConn, error) {
|
|||||||
}
|
}
|
||||||
c := &ServerConn{Conn: conn}
|
c := &ServerConn{Conn: conn}
|
||||||
|
|
||||||
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before client/ticket hello
|
_, t, l, err := ReadAndDiscardPaddings(c.Conn, nil, nil) // allow paddings before client/ticket hello
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -171,11 +171,14 @@ func (i *ServerInstance) Handshake(conn net.Conn) (*ServerConn, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
nfsAEAD := NewAEAD(c.cipher, nfsKey, pfsEKeyBytes, encapsulatedNfsKey)
|
||||||
|
nfsNonce := append([]byte{}, peerClientHello[:11+1]...)
|
||||||
pfsKey, encapsulatedPfsKey := pfsEKey.Encapsulate()
|
pfsKey, encapsulatedPfsKey := pfsEKey.Encapsulate()
|
||||||
c.baseKey = append(pfsKey, nfsKey...)
|
c.baseKey = append(pfsKey, nfsKey...)
|
||||||
pfsAEAD := NewAEAD(c.cipher, c.baseKey, encapsulatedPfsKey, encapsulatedNfsKey)
|
pfsAEAD := NewAEAD(c.cipher, c.baseKey, encapsulatedPfsKey, encapsulatedNfsKey)
|
||||||
c.ticket = append(i.hash11[:], pfsAEAD.Seal(nil, peerClientHello[:11+1], []byte("VLESS"), pfsEKeyBytes)...)
|
pfsNonce := append([]byte{}, peerClientHello[:11+1]...)
|
||||||
IncreaseNonce(peerClientHello[:11+1])
|
c.ticket = append(i.hash11[:], pfsAEAD.Seal(nil, pfsNonce, []byte("VLESS"), pfsEKeyBytes)...)
|
||||||
|
IncreaseNonce(pfsNonce)
|
||||||
|
|
||||||
serverHello := make([]byte, 5+1088+21+crypto.RandBetween(100, 1000))
|
serverHello := make([]byte, 5+1088+21+crypto.RandBetween(100, 1000))
|
||||||
EncodeHeader(serverHello, 1, 1088+21)
|
EncodeHeader(serverHello, 1, 1088+21)
|
||||||
@ -184,20 +187,41 @@ func (i *ServerInstance) Handshake(conn net.Conn) (*ServerConn, error) {
|
|||||||
padding := serverHello[5+1088+21:]
|
padding := serverHello[5+1088+21:]
|
||||||
rand.Read(padding) // important
|
rand.Read(padding) // important
|
||||||
EncodeHeader(padding, 23, len(padding)-5)
|
EncodeHeader(padding, 23, len(padding)-5)
|
||||||
pfsAEAD.Seal(padding[:5], peerClientHello[:11+1], padding[5:len(padding)-16], padding[:5])
|
pfsAEAD.Seal(padding[:5], pfsNonce, padding[5:len(padding)-16], padding[:5])
|
||||||
|
|
||||||
if _, err := c.Conn.Write(serverHello); err != nil {
|
if _, err := c.Conn.Write(serverHello); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// server can send more PFS AEAD paddings / messages if needed
|
// server can send more PFS AEAD paddings / messages if needed
|
||||||
|
|
||||||
|
_, t, l, err = ReadAndDiscardPaddings(c.Conn, nfsAEAD, nfsNonce) // allow paddings before ticket hello
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if t != 0 {
|
||||||
|
return nil, errors.New("unexpected type ", t, ", expect ticket hello")
|
||||||
|
}
|
||||||
|
peerTicketHello := make([]byte, 32+32)
|
||||||
|
if l != len(peerTicketHello) {
|
||||||
|
return nil, errors.New("unexpected length ", l, " for ticket hello")
|
||||||
|
}
|
||||||
|
if _, err := io.ReadFull(c.Conn, peerTicketHello); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !bytes.Equal(peerTicketHello[:32], c.ticket) {
|
||||||
|
return nil, errors.New("naughty boy")
|
||||||
|
}
|
||||||
|
c.peerRandom = peerTicketHello[32:]
|
||||||
|
|
||||||
if i.minutes > 0 {
|
if i.minutes > 0 {
|
||||||
i.Lock()
|
i.Lock()
|
||||||
i.sessions[[32]byte(c.ticket)] = &ServerSession{
|
s := &ServerSession{
|
||||||
expire: time.Now().Add(i.minutes),
|
expire: time.Now().Add(i.minutes),
|
||||||
cipher: c.cipher,
|
cipher: c.cipher,
|
||||||
baseKey: c.baseKey,
|
baseKey: c.baseKey,
|
||||||
}
|
}
|
||||||
|
s.randoms.Store([32]byte(c.peerRandom), true)
|
||||||
|
i.sessions[[32]byte(c.ticket)] = s
|
||||||
i.Unlock()
|
i.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,26 +233,6 @@ func (c *ServerConn) Read(b []byte) (int, error) {
|
|||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
if c.peerAEAD == nil {
|
if c.peerAEAD == nil {
|
||||||
if c.peerRandom == nil { // 1-RTT's 0-RTT
|
|
||||||
_, t, l, err := ReadAndDiscardPaddings(c.Conn) // allow paddings before ticket hello
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
if t != 0 {
|
|
||||||
return 0, errors.New("unexpected type ", t, ", expect ticket hello")
|
|
||||||
}
|
|
||||||
peerTicketHello := make([]byte, 32+32)
|
|
||||||
if l != len(peerTicketHello) {
|
|
||||||
return 0, errors.New("unexpected length ", l, " for ticket hello")
|
|
||||||
}
|
|
||||||
if _, err := io.ReadFull(c.Conn, peerTicketHello); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
if !bytes.Equal(peerTicketHello[:32], c.ticket) {
|
|
||||||
return 0, errors.New("naughty boy")
|
|
||||||
}
|
|
||||||
c.peerRandom = peerTicketHello[32:]
|
|
||||||
}
|
|
||||||
c.peerAEAD = NewAEAD(c.cipher, c.baseKey, c.peerRandom, c.ticket)
|
c.peerAEAD = NewAEAD(c.cipher, c.baseKey, c.peerRandom, c.ticket)
|
||||||
c.peerNonce = make([]byte, 12)
|
c.peerNonce = make([]byte, 12)
|
||||||
}
|
}
|
||||||
@ -283,9 +287,6 @@ func (c *ServerConn) Write(b []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
n += len(b)
|
n += len(b)
|
||||||
if c.aead == nil {
|
if c.aead == nil {
|
||||||
if c.peerRandom == nil {
|
|
||||||
return 0, errors.New("empty c.peerRandom")
|
|
||||||
}
|
|
||||||
data = make([]byte, 5+32+5+len(b)+16)
|
data = make([]byte, 5+32+5+len(b)+16)
|
||||||
EncodeHeader(data, 0, 32)
|
EncodeHeader(data, 0, 32)
|
||||||
rand.Read(data[5 : 5+32])
|
rand.Read(data[5 : 5+32])
|
||||||
|
Loading…
Reference in New Issue
Block a user