diff --git a/pkg/tcpip/transport/tcp/connect.go b/pkg/tcpip/transport/tcp/connect.go index 5daf30d10..67c69f6ef 100644 --- a/pkg/tcpip/transport/tcp/connect.go +++ b/pkg/tcpip/transport/tcp/connect.go @@ -15,6 +15,7 @@ package tcp import ( + "crypto/sha256" "encoding/binary" "fmt" "math" @@ -23,7 +24,6 @@ import ( "gvisor.dev/gvisor/pkg/sync" "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip/checksum" - "gvisor.dev/gvisor/pkg/tcpip/hash/jenkins" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/seqnum" "gvisor.dev/gvisor/pkg/tcpip/stack" @@ -236,10 +236,14 @@ 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 { - isnHasher := jenkins.Sum32(seed) + 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(id.LocalAddress.AsSlice()) _, _ = isnHasher.Write(id.RemoteAddress.AsSlice()) portBuf := make([]byte, 2) @@ -257,7 +261,8 @@ func generateSecureISN(id stack.TransportEndpointID, clock tcpip.Clock, seed uin // // Which sort of guarantees that we won't reuse the ISN for a new // connection for the same tuple for at least 274s. - isn := isnHasher.Sum32() + uint32(clock.NowMonotonic().Sub(tcpip.MonotonicTime{}).Nanoseconds()>>6) + hash := binary.LittleEndian.Uint32(isnHasher.Sum(nil)[:4]) + isn := hash + uint32(clock.NowMonotonic().Sub(tcpip.MonotonicTime{}).Nanoseconds()>>6) return seqnum.Value(isn) } diff --git a/pkg/tcpip/transport/tcp/protocol.go b/pkg/tcpip/transport/tcp/protocol.go index 555951488..090fc6e9d 100644 --- a/pkg/tcpip/transport/tcp/protocol.go +++ b/pkg/tcpip/transport/tcp/protocol.go @@ -16,13 +16,14 @@ package tcp import ( + "crypto/sha256" + "encoding/binary" "runtime" "strings" "time" "gvisor.dev/gvisor/pkg/sync" "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/hash/jenkins" "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/header/parse" "gvisor.dev/gvisor/pkg/tcpip/internal/tcp" @@ -178,16 +179,17 @@ func (p *protocol) tsOffset(src, dst tcpip.Address) tcp.TSOffset { // // See https://tools.ietf.org/html/rfc7323#section-5.4 for details on // why this is required. - // - // TODO(https://gvisor.dev/issues/6473): This is not really secure as - // it does not use the recommended algorithm linked above. - h := jenkins.Sum32(p.tsOffsetSecret) + 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(src.AsSlice()) _, _ = h.Write(dst.AsSlice()) - return tcp.NewTSOffset(h.Sum32()) + return tcp.NewTSOffset(binary.LittleEndian.Uint32(h.Sum(nil)[:4])) } // replyWithReset replies to the given segment with a reset segment.