From e54bfde79278cafadedbf73c68ee10cb5982f2af Mon Sep 17 00:00:00 2001 From: Zeling Feng Date: Tue, 21 Nov 2023 22:37:32 -0800 Subject: [PATCH] Use 16-byte secret for SHA2 4-byte secrets are too short for SHA hash algorithm. PiperOrigin-RevId: 584518939 --- pkg/tcpip/transport/tcp/connect.go | 6 ++---- pkg/tcpip/transport/tcp/protocol.go | 23 ++++++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/pkg/tcpip/transport/tcp/connect.go b/pkg/tcpip/transport/tcp/connect.go index 67c69f6ef..705021d28 100644 --- a/pkg/tcpip/transport/tcp/connect.go +++ b/pkg/tcpip/transport/tcp/connect.go @@ -235,15 +235,13 @@ func (h *handshake) resetState() { // generateSecureISN generates a secure Initial Sequence number based on the // recommendation here https://tools.ietf.org/html/rfc6528#page-3. -func generateSecureISN(id stack.TransportEndpointID, clock tcpip.Clock, seed uint32) seqnum.Value { +func generateSecureISN(id stack.TransportEndpointID, clock tcpip.Clock, seed [16]byte) seqnum.Value { isnHasher := sha256.New() - seedBuf := make([]byte, 4) - binary.LittleEndian.PutUint32(seedBuf, seed) // Per hash.Hash.Writer: // // It never returns an error. - _, _ = isnHasher.Write(seedBuf) + _, _ = isnHasher.Write(seed[:]) _, _ = isnHasher.Write(id.LocalAddress.AsSlice()) _, _ = isnHasher.Write(id.RemoteAddress.AsSlice()) portBuf := make([]byte, 2) diff --git a/pkg/tcpip/transport/tcp/protocol.go b/pkg/tcpip/transport/tcp/protocol.go index 090fc6e9d..37c6fb6ab 100644 --- a/pkg/tcpip/transport/tcp/protocol.go +++ b/pkg/tcpip/transport/tcp/protocol.go @@ -18,6 +18,7 @@ package tcp import ( "crypto/sha256" "encoding/binary" + "fmt" "runtime" "strings" "time" @@ -108,9 +109,8 @@ type protocol struct { dispatcher dispatcher // The following secrets are initialized once and stay unchanged after. - seqnumSecret uint32 - portOffsetSecret uint32 - tsOffsetSecret uint32 + seqnumSecret [16]byte + tsOffsetSecret [16]byte } // Number returns the tcp protocol number. @@ -181,12 +181,10 @@ func (p *protocol) tsOffset(src, dst tcpip.Address) tcp.TSOffset { // why this is required. h := sha256.New() - secretBuf := make([]byte, 4) - binary.LittleEndian.PutUint32(secretBuf, p.tsOffsetSecret) // Per hash.Hash.Writer: // // It never returns an error. - _, _ = h.Write(secretBuf) + _, _ = h.Write(p.tsOffsetSecret[:]) _, _ = h.Write(src.AsSlice()) _, _ = h.Write(dst.AsSlice()) return tcp.NewTSOffset(binary.LittleEndian.Uint32(h.Sum(nil)[:4])) @@ -510,6 +508,14 @@ func (*protocol) Parse(pkt stack.PacketBufferPtr) bool { // NewProtocol returns a TCP transport protocol. func NewProtocol(s *stack.Stack) stack.TransportProtocol { rng := s.SecureRNG() + var seqnumSecret [16]byte + var tsOffsetSecret [16]byte + if n, err := rng.Reader.Read(seqnumSecret[:]); err != nil || n != len(seqnumSecret) { + panic(fmt.Sprintf("Read() failed: %v", err)) + } + if n, err := rng.Reader.Read(tsOffsetSecret[:]); err != nil || n != len(tsOffsetSecret) { + panic(fmt.Sprintf("Read() failed: %v", err)) + } p := protocol{ stack: s, sendBufferSize: tcpip.TCPSendBufferSizeRangeOption{ @@ -533,9 +539,8 @@ func NewProtocol(s *stack.Stack) stack.TransportProtocol { maxRTO: MaxRTO, maxRetries: MaxRetries, recovery: tcpip.TCPRACKLossDetection, - seqnumSecret: rng.Uint32(), - portOffsetSecret: rng.Uint32(), - tsOffsetSecret: rng.Uint32(), + seqnumSecret: seqnumSecret, + tsOffsetSecret: tsOffsetSecret, } p.dispatcher.init(s.InsecureRNG(), runtime.GOMAXPROCS(0)) return &p