173
common/ktls/ktls_key_update.go
Normal file
173
common/ktls/ktls_key_update.go
Normal file
@@ -0,0 +1,173 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux && go1.25 && !without_badtls
|
||||
|
||||
package ktls
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// handlePostHandshakeMessage processes a handshake message arrived after the
|
||||
// handshake is complete. Up to TLS 1.2, it indicates the start of a renegotiation.
|
||||
func (c *Conn) handlePostHandshakeMessage() error {
|
||||
if *c.rawConn.Vers != tls.VersionTLS13 {
|
||||
return errors.New("ktls: kernel does not support TLS 1.2 renegotiation")
|
||||
}
|
||||
|
||||
msg, err := c.readHandshake(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//c.retryCount++
|
||||
//if c.retryCount > maxUselessRecords {
|
||||
// c.sendAlert(alertUnexpectedMessage)
|
||||
// return c.in.setErrorLocked(errors.New("tls: too many non-advancing records"))
|
||||
//}
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case *newSessionTicketMsgTLS13:
|
||||
// return errors.New("ktls: received new session ticket")
|
||||
return nil
|
||||
case *keyUpdateMsg:
|
||||
return c.handleKeyUpdate(msg)
|
||||
}
|
||||
// The QUIC layer is supposed to treat an unexpected post-handshake CertificateRequest
|
||||
// as a QUIC-level PROTOCOL_VIOLATION error (RFC 9001, Section 4.4). Returning an
|
||||
// unexpected_message alert here doesn't provide it with enough information to distinguish
|
||||
// this condition from other unexpected messages. This is probably fine.
|
||||
c.sendAlert(alertUnexpectedMessage)
|
||||
return fmt.Errorf("tls: received unexpected handshake message of type %T", msg)
|
||||
}
|
||||
|
||||
func (c *Conn) handleKeyUpdate(keyUpdate *keyUpdateMsg) error {
|
||||
//if c.quic != nil {
|
||||
// c.sendAlert(alertUnexpectedMessage)
|
||||
// return c.in.setErrorLocked(errors.New("tls: received unexpected key update message"))
|
||||
//}
|
||||
|
||||
cipherSuite := cipherSuiteTLS13ByID(*c.rawConn.CipherSuite)
|
||||
if cipherSuite == nil {
|
||||
return c.rawConn.In.SetErrorLocked(c.sendAlert(alertInternalError))
|
||||
}
|
||||
|
||||
newSecret := nextTrafficSecret(cipherSuite, *c.rawConn.In.TrafficSecret)
|
||||
c.rawConn.In.SetTrafficSecret(cipherSuite, 0 /*tls.QUICEncryptionLevelInitial*/, newSecret)
|
||||
|
||||
err := c.resetupRX()
|
||||
if err != nil {
|
||||
c.sendAlert(alertInternalError)
|
||||
return c.rawConn.In.SetErrorLocked(fmt.Errorf("ktls: resetupRX failed: %w", err))
|
||||
}
|
||||
|
||||
if keyUpdate.updateRequested {
|
||||
c.rawConn.Out.Lock()
|
||||
defer c.rawConn.Out.Unlock()
|
||||
|
||||
resetup, err := c.resetupTX()
|
||||
if err != nil {
|
||||
c.sendAlertLocked(alertInternalError)
|
||||
return c.rawConn.Out.SetErrorLocked(fmt.Errorf("ktls: resetupTX failed: %w", err))
|
||||
}
|
||||
|
||||
msg := &keyUpdateMsg{}
|
||||
msgBytes, err := msg.marshal()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = c.writeRecordLocked(recordTypeHandshake, msgBytes)
|
||||
if err != nil {
|
||||
// Surface the error at the next write.
|
||||
c.rawConn.Out.SetErrorLocked(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
newSecret := nextTrafficSecret(cipherSuite, *c.rawConn.Out.TrafficSecret)
|
||||
c.rawConn.Out.SetTrafficSecret(cipherSuite, 0 /*QUICEncryptionLevelInitial*/, newSecret)
|
||||
|
||||
err = resetup()
|
||||
if err != nil {
|
||||
return c.rawConn.Out.SetErrorLocked(fmt.Errorf("ktls: resetupTX failed: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) readHandshakeBytes(n int) error {
|
||||
//if c.quic != nil {
|
||||
// return c.quicReadHandshakeBytes(n)
|
||||
//}
|
||||
for c.rawConn.Hand.Len() < n {
|
||||
if err := c.readRecord(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Conn) readHandshake(transcript io.Writer) (any, error) {
|
||||
if err := c.readHandshakeBytes(4); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data := c.rawConn.Hand.Bytes()
|
||||
|
||||
maxHandshakeSize := maxHandshake
|
||||
// hasVers indicates we're past the first message, forcing someone trying to
|
||||
// make us just allocate a large buffer to at least do the initial part of
|
||||
// the handshake first.
|
||||
//if c.haveVers && data[0] == typeCertificate {
|
||||
// Since certificate messages are likely to be the only messages that
|
||||
// can be larger than maxHandshake, we use a special limit for just
|
||||
// those messages.
|
||||
//maxHandshakeSize = maxHandshakeCertificateMsg
|
||||
//}
|
||||
|
||||
n := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
|
||||
if n > maxHandshakeSize {
|
||||
c.sendAlertLocked(alertInternalError)
|
||||
return nil, c.rawConn.In.SetErrorLocked(fmt.Errorf("tls: handshake message of length %d bytes exceeds maximum of %d bytes", n, maxHandshakeSize))
|
||||
}
|
||||
if err := c.readHandshakeBytes(4 + n); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data = c.rawConn.Hand.Next(4 + n)
|
||||
return c.unmarshalHandshakeMessage(data, transcript)
|
||||
}
|
||||
|
||||
func (c *Conn) unmarshalHandshakeMessage(data []byte, transcript io.Writer) (any, error) {
|
||||
var m handshakeMessage
|
||||
switch data[0] {
|
||||
case typeNewSessionTicket:
|
||||
if *c.rawConn.Vers == tls.VersionTLS13 {
|
||||
m = new(newSessionTicketMsgTLS13)
|
||||
} else {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
case typeKeyUpdate:
|
||||
m = new(keyUpdateMsg)
|
||||
default:
|
||||
return nil, c.rawConn.In.SetErrorLocked(c.sendAlert(alertUnexpectedMessage))
|
||||
}
|
||||
|
||||
// The handshake message unmarshalers
|
||||
// expect to be able to keep references to data,
|
||||
// so pass in a fresh copy that won't be overwritten.
|
||||
data = append([]byte(nil), data...)
|
||||
|
||||
if !m.unmarshal(data) {
|
||||
return nil, c.rawConn.In.SetErrorLocked(c.sendAlert(alertDecodeError))
|
||||
}
|
||||
|
||||
if transcript != nil {
|
||||
transcript.Write(data)
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
Reference in New Issue
Block a user