123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- // 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 && badlinkname
- package ktls
- import (
- "crypto/cipher"
- "crypto/tls"
- "errors"
- "net"
- )
- func (c *Conn) Write(b []byte) (int, error) {
- if !c.kernelTx {
- return c.Conn.Write(b)
- }
- // interlock with Close below
- for {
- x := c.rawConn.ActiveCall.Load()
- if x&1 != 0 {
- return 0, net.ErrClosed
- }
- if c.rawConn.ActiveCall.CompareAndSwap(x, x+2) {
- break
- }
- }
- defer c.rawConn.ActiveCall.Add(-2)
- //if err := c.Conn.HandshakeContext(context.Background()); err != nil {
- // return 0, err
- //}
- c.rawConn.Out.Lock()
- defer c.rawConn.Out.Unlock()
- if err := *c.rawConn.Out.Err; err != nil {
- return 0, err
- }
- if !c.rawConn.IsHandshakeComplete.Load() {
- return 0, tls.AlertError(alertInternalError)
- }
- if *c.rawConn.CloseNotifySent {
- // return 0, errShutdown
- return 0, errors.New("tls: protocol is shutdown")
- }
- // TLS 1.0 is susceptible to a chosen-plaintext
- // attack when using block mode ciphers due to predictable IVs.
- // This can be prevented by splitting each Application Data
- // record into two records, effectively randomizing the RawIV.
- //
- // https://www.openssl.org/~bodo/tls-cbc.txt
- // https://bugzilla.mozilla.org/show_bug.cgi?id=665814
- // https://www.imperialviolet.org/2012/01/15/beastfollowup.html
- var m int
- if len(b) > 1 && *c.rawConn.Vers == tls.VersionTLS10 {
- if _, ok := (*c.rawConn.Out.Cipher).(cipher.BlockMode); ok {
- n, err := c.writeRecordLocked(recordTypeApplicationData, b[:1])
- if err != nil {
- return n, c.rawConn.Out.SetErrorLocked(err)
- }
- m, b = 1, b[1:]
- }
- }
- n, err := c.writeRecordLocked(recordTypeApplicationData, b)
- return n + m, c.rawConn.Out.SetErrorLocked(err)
- }
- func (c *Conn) writeRecordLocked(typ uint16, data []byte) (n int, err error) {
- if !c.kernelTx {
- return c.rawConn.WriteRecordLocked(typ, data)
- }
- /*for len(data) > 0 {
- m := len(data)
- if maxPayload := c.maxPayloadSizeForWrite(typ); m > maxPayload {
- m = maxPayload
- }
- _, err = c.writeKernelRecord(typ, data[:m])
- if err != nil {
- return
- }
- n += m
- data = data[m:]
- }*/
- return c.writeKernelRecord(typ, data)
- }
- const (
- // tcpMSSEstimate is a conservative estimate of the TCP maximum segment
- // size (MSS). A constant is used, rather than querying the kernel for
- // the actual MSS, to avoid complexity. The value here is the IPv6
- // minimum MTU (1280 bytes) minus the overhead of an IPv6 header (40
- // bytes) and a TCP header with timestamps (32 bytes).
- tcpMSSEstimate = 1208
- // recordSizeBoostThreshold is the number of bytes of application data
- // sent after which the TLS record size will be increased to the
- // maximum.
- recordSizeBoostThreshold = 128 * 1024
- )
- func (c *Conn) maxPayloadSizeForWrite(typ uint16) int {
- if /*c.config.DynamicRecordSizingDisabled ||*/ typ != recordTypeApplicationData {
- return maxPlaintext
- }
- if *c.rawConn.PacketsSent >= recordSizeBoostThreshold {
- return maxPlaintext
- }
- // Subtract TLS overheads to get the maximum payload size.
- payloadBytes := tcpMSSEstimate - recordHeaderLen - c.rawConn.Out.ExplicitNonceLen()
- if rawCipher := *c.rawConn.Out.Cipher; rawCipher != nil {
- switch ciph := rawCipher.(type) {
- case cipher.Stream:
- payloadBytes -= (*c.rawConn.Out.Mac).Size()
- case cipher.AEAD:
- payloadBytes -= ciph.Overhead()
- /*case cbcMode:
- blockSize := ciph.BlockSize()
- // The payload must fit in a multiple of blockSize, with
- // room for at least one padding byte.
- payloadBytes = (payloadBytes & ^(blockSize - 1)) - 1
- // The RawMac is appended before padding so affects the
- // payload size directly.
- payloadBytes -= c.out.mac.Size()*/
- default:
- panic("unknown cipher type")
- }
- }
- if *c.rawConn.Vers == tls.VersionTLS13 {
- payloadBytes-- // encrypted ContentType
- }
- // Allow packet growth in arithmetic progression up to max.
- pkt := *c.rawConn.PacketsSent
- *c.rawConn.PacketsSent++
- if pkt > 1000 {
- return maxPlaintext // avoid overflow in multiply below
- }
- n := payloadBytes * int(pkt+1)
- if n > maxPlaintext {
- n = maxPlaintext
- }
- return n
- }
|