Copyright 2010 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.
TLS low level connection and record layer

package tls

import (
	
	
	
	
	
	
	
	
	
	
	
	
)
A Conn represents a secured connection. It implements the net.Conn interface.
constant
	conn        net.Conn
	isClient    bool
	handshakeFn func() error // (*Conn).clientHandshake or serverHandshake
handshakeStatus is 1 if the connection is currently transferring application data (i.e. is not currently processing a handshake). This field is only to be accessed with sync/atomic.
constant after handshake; protected by handshakeMutex
	handshakeMutex sync.Mutex
	handshakeErr   error   // error resulting from handshake
	vers           uint16  // TLS version
	haveVers       bool    // version has been negotiated
handshakes counts the number of handshakes performed on the connection so far. If renegotiation is disabled then this is either zero or one.
	handshakes       int
	didResume        bool // whether this connection was a session resumption
	cipherSuite      uint16
	ocspResponse     []byte   // stapled OCSP response
	scts             [][]byte // signed certificate timestamps from server
verifiedChains contains the certificate chains that we built, as opposed to the ones presented by the server.
serverName contains the server name indicated by the client, if any.
secureRenegotiation is true if the server echoed the secure renegotiation extension. (This is meaningless as a server because renegotiation is not supported in that case.)
ekm is a closure for exporting keying material.
resumptionSecret is the resumption_master_secret for handling NewSessionTicket messages. nil if config.SessionTicketsDisabled.
ticketKeys is the set of active session ticket keys for this connection. The first one is used to encrypt new tickets and all are tried to decrypt tickets.
clientFinishedIsFirst is true if the client sent the first Finished message during the most recent handshake. This is recorded because the first transmitted Finished message is the tls-unique channel-binding value.
closeNotifyErr is any error from sending the alertCloseNotify record.
closeNotifySent is true if the Conn attempted to send an alertCloseNotify record.
clientFinished and serverFinished contain the Finished message sent by the client or server in the most recent handshake. This is retained to support the renegotiation extension and tls-unique channel-binding.
clientProtocol is the negotiated ALPN protocol.
input/output
	in, out   halfConn
	rawInput  bytes.Buffer // raw input, starting with a record header
	input     bytes.Reader // application data waiting to be read, from rawInput.Next
	hand      bytes.Buffer // handshake data waiting to be read
	buffering bool         // whether records are buffered in sendBuf
	sendBuf   []byte       // a buffer of records waiting to be sent
bytesSent counts the bytes of application data sent. packetsSent counts packets.
retryCount counts the number of consecutive non-advancing records received by Conn.readRecord. That is, records that neither advance the handshake, nor deliver application data. Protected by in.Mutex.
activeCall is an atomic int32; the low bit is whether Close has been called. the rest of the bits are the number of goroutines in Conn.Write.
Access to net.Conn methods. Cannot just embed net.Conn because that would export the struct field too.
LocalAddr returns the local network address.
func ( *Conn) () net.Addr {
	return .conn.LocalAddr()
}
RemoteAddr returns the remote network address.
func ( *Conn) () net.Addr {
	return .conn.RemoteAddr()
}
SetDeadline sets the read and write deadlines associated with the connection. A zero value for t means Read and Write will not time out. After a Write has timed out, the TLS state is corrupt and all future writes will return the same error.
func ( *Conn) ( time.Time) error {
	return .conn.SetDeadline()
}
SetReadDeadline sets the read deadline on the underlying connection. A zero value for t means Read will not time out.
func ( *Conn) ( time.Time) error {
	return .conn.SetReadDeadline()
}
SetWriteDeadline sets the write deadline on the underlying connection. A zero value for t means Write will not time out. After a Write has timed out, the TLS state is corrupt and all future writes will return the same error.
func ( *Conn) ( time.Time) error {
	return .conn.SetWriteDeadline()
}
A halfConn represents one direction of the record layer connection, either sending or receiving.
type halfConn struct {
	sync.Mutex

	err     error       // first permanent error
	version uint16      // protocol version
	cipher  interface{} // cipher algorithm
	mac     hash.Hash
	seq     [8]byte // 64-bit sequence number

	scratchBuf [13]byte // to avoid allocs; interface method args escape

	nextCipher interface{} // next encryption state
	nextMac    hash.Hash   // next MAC algorithm

	trafficSecret []byte // current TLS 1.3 traffic secret
}

type permanentError struct {
	err net.Error
}

func ( *permanentError) () string   { return .err.Error() }
func ( *permanentError) () error   { return .err }
func ( *permanentError) () bool   { return .err.Timeout() }
func ( *permanentError) () bool { return false }

func ( *halfConn) ( error) error {
	if ,  := .(net.Error);  {
		.err = &permanentError{err: }
	} else {
		.err = 
	}
	return .err
}
prepareCipherSpec sets the encryption and MAC states that a subsequent changeCipherSpec will use.
func ( *halfConn) ( uint16,  interface{},  hash.Hash) {
	.version = 
	.nextCipher = 
	.nextMac = 
}
changeCipherSpec changes the encryption and MAC states to the ones previously passed to prepareCipherSpec.
func ( *halfConn) () error {
	if .nextCipher == nil || .version == VersionTLS13 {
		return alertInternalError
	}
	.cipher = .nextCipher
	.mac = .nextMac
	.nextCipher = nil
	.nextMac = nil
	for  := range .seq {
		.seq[] = 0
	}
	return nil
}

func ( *halfConn) ( *cipherSuiteTLS13,  []byte) {
	.trafficSecret = 
	,  := .trafficKey()
	.cipher = .aead(, )
	for  := range .seq {
		.seq[] = 0
	}
}
incSeq increments the sequence number.
func ( *halfConn) () {
	for  := 7;  >= 0; -- {
		.seq[]++
		if .seq[] != 0 {
			return
		}
	}
Not allowed to let sequence number wrap. Instead, must renegotiate before it does. Not likely enough to bother.
	panic("TLS: sequence number wraparound")
}
explicitNonceLen returns the number of bytes of explicit nonce or IV included in each record. Explicit nonces are present only in CBC modes after TLS 1.0 and in certain AEAD modes in TLS 1.2.
func ( *halfConn) () int {
	if .cipher == nil {
		return 0
	}

	switch c := .cipher.(type) {
	case cipher.Stream:
		return 0
	case aead:
		return .explicitNonceLen()
TLS 1.1 introduced a per-record explicit IV to fix the BEAST attack.
		if .version >= VersionTLS11 {
			return .BlockSize()
		}
		return 0
	default:
		panic("unknown cipher type")
	}
}
extractPadding returns, in constant time, the length of the padding to remove from the end of payload. It also returns a byte which is equal to 255 if the padding was valid and 0 otherwise. See RFC 2246, Section 6.2.3.2.
func ( []byte) ( int,  byte) {
	if len() < 1 {
		return 0, 0
	}

	 := [len()-1]
if len(payload) >= (paddingLen - 1) then the MSB of t is zero
	 = byte(int32(^) >> 31)
The maximum possible padding length plus the actual length field
The length of the padded data is public, so we can use an if here
	if  > len() {
		 = len()
	}

	for  := 0;  < ; ++ {
if i <= paddingLen then the MSB of t is zero
		 := byte(int32(^) >> 31)
		 := [len()-1-]
		 &^= & ^ &
	}
We AND together the bits of good and replicate the result across all the bits.
	 &=  << 4
	 &=  << 2
	 &=  << 1
	 = uint8(int8() >> 7)
Zero the padding length on error. This ensures any unchecked bytes are included in the MAC. Otherwise, an attacker that could distinguish MAC failures from padding failures could mount an attack similar to POODLE in SSL 3.0: given a good ciphertext that uses a full block's worth of padding, replace the final block with another block. If the MAC check passed but the padding check failed, the last byte of that block decrypted to the block size. See also macAndPaddingGood logic below.
	 &= 

	 = int() + 1
	return
}

func (,  int) int {
	return  + (-%)%
}
cbcMode is an interface for block ciphers using cipher block chaining.
type cbcMode interface {
	cipher.BlockMode
	SetIV([]byte)
}
decrypt authenticates and decrypts the record if protection is active at this stage. The returned plaintext might overlap with the input.
func ( *halfConn) ( []byte) ([]byte, recordType, error) {
	var  []byte
	 := recordType([0])
	 := [recordHeaderLen:]
In TLS 1.3, change_cipher_spec messages are to be ignored without being decrypted. See RFC 8446, Appendix D.4.
	if .version == VersionTLS13 &&  == recordTypeChangeCipherSpec {
		return , , nil
	}

	 := byte(255)
	 := 0

	 := .explicitNonceLen()

	if .cipher != nil {
		switch c := .cipher.(type) {
		case cipher.Stream:
			.XORKeyStream(, )
		case aead:
			if len() <  {
				return nil, 0, alertBadRecordMAC
			}
			 := [:]
			if len() == 0 {
				 = .seq[:]
			}
			 = [:]

			var  []byte
			if .version == VersionTLS13 {
				 = [:recordHeaderLen]
			} else {
				 = append(.scratchBuf[:0], .seq[:]...)
				 = append(, [:3]...)
				 := len() - .Overhead()
				 = append(, byte(>>8), byte())
			}

			var  error
			,  = .Open([:0], , , )
			if  != nil {
				return nil, 0, alertBadRecordMAC
			}
		case cbcMode:
			 := .BlockSize()
			 :=  + roundUp(.mac.Size()+1, )
			if len()% != 0 || len() <  {
				return nil, 0, alertBadRecordMAC
			}

			if  > 0 {
				.SetIV([:])
				 = [:]
			}
			.CryptBlocks(, )
In a limited attempt to protect against CBC padding oracles like Lucky13, the data past paddingLen (which is secret) is passed to the MAC function as extra data, to be fed into the HMAC after computing the digest. This makes the MAC roughly constant time as long as the digest computation is constant time and does not affect the subsequent write, modulo cache effects.
			,  = extractPadding()
		default:
			panic("unknown cipher type")
		}

		if .version == VersionTLS13 {
			if  != recordTypeApplicationData {
				return nil, 0, alertUnexpectedMessage
			}
			if len() > maxPlaintext+1 {
				return nil, 0, alertRecordOverflow
Remove padding and find the ContentType scanning from the end.
			for  := len() - 1;  >= 0; -- {
				if [] != 0 {
					 = recordType([])
					 = [:]
					break
				}
				if  == 0 {
					return nil, 0, alertUnexpectedMessage
				}
			}
		}
	} else {
		 = 
	}

	if .mac != nil {
		 := .mac.Size()
		if len() <  {
			return nil, 0, alertBadRecordMAC
		}

		 := len() -  - 
		 = subtle.ConstantTimeSelect(int(uint32()>>31), 0, ) // if n < 0 { n = 0 }
		[3] = byte( >> 8)
		[4] = byte()
		 := [ : +]
		 := tls10MAC(.mac, .scratchBuf[:0], .seq[:], [:recordHeaderLen], [:], [+:])
This is equivalent to checking the MACs and paddingGood separately, but in constant-time to prevent distinguishing padding failures from MAC failures. Depending on what value of paddingLen was returned on bad padding, distinguishing bad MAC from bad padding can lead to an attack. See also the logic at the end of extractPadding.
		 := subtle.ConstantTimeCompare(, ) & int()
		if  != 1 {
			return nil, 0, alertBadRecordMAC
		}

		 = [:]
	}

	.incSeq()
	return , , nil
}
sliceForAppend extends the input slice by n bytes. head is the full extended slice, while tail is the appended part. If the original slice has sufficient capacity no allocation is performed.
func ( []byte,  int) (,  []byte) {
	if  := len() + ; cap() >=  {
		 = [:]
	} else {
		 = make([]byte, )
		copy(, )
	}
	 = [len():]
	return
}
encrypt encrypts payload, adding the appropriate nonce and/or MAC, and appends it to record, which must already contain the record header.
func ( *halfConn) (,  []byte,  io.Reader) ([]byte, error) {
	if .cipher == nil {
		return append(, ...), nil
	}

	var  []byte
	if  := .explicitNonceLen();  > 0 {
		,  = sliceForAppend(, )
The AES-GCM construction in TLS has an explicit nonce so that the nonce can be random. However, the nonce is only 8 bytes which is too small for a secure, random nonce. Therefore we use the sequence number as the nonce. The 3DES-CBC construction also has an 8 bytes nonce but its nonces must be unpredictable (see RFC 5246, Appendix F.3), forcing us to use randomness. That's not 3DES' biggest problem anyway because the birthday bound on block collision is reached first due to its similarly small block size (see the Sweet32 attack).
			copy(, .seq[:])
		} else {
			if ,  := io.ReadFull(, );  != nil {
				return nil, 
			}
		}
	}

	var  []byte
	switch c := .cipher.(type) {
	case cipher.Stream:
		 := tls10MAC(.mac, .scratchBuf[:0], .seq[:], [:recordHeaderLen], , nil)
		,  = sliceForAppend(, len()+len())
		.XORKeyStream([:len()], )
		.XORKeyStream([len():], )
	case aead:
		 := 
		if len() == 0 {
			 = .seq[:]
		}

		if .version == VersionTLS13 {
			 = append(, ...)
Encrypt the actual ContentType and replace the plaintext one.
			 = append(, [0])
			[0] = byte(recordTypeApplicationData)

			 := len() + 1 + .Overhead()
			[3] = byte( >> 8)
			[4] = byte()

			 = .Seal([:recordHeaderLen],
				, [recordHeaderLen:], [:recordHeaderLen])
		} else {
			 := append(.scratchBuf[:0], .seq[:]...)
			 = append(, [:recordHeaderLen]...)
			 = .Seal(, , , )
		}
	case cbcMode:
		 := tls10MAC(.mac, .scratchBuf[:0], .seq[:], [:recordHeaderLen], , nil)
		 := .BlockSize()
		 := len() + len()
		 :=  - %
		,  = sliceForAppend(, +)
		copy(, )
		copy([len():], )
		for  := ;  < len(); ++ {
			[] = byte( - 1)
		}
		if len() > 0 {
			.SetIV()
		}
		.CryptBlocks(, )
	default:
		panic("unknown cipher type")
	}
Update length to include nonce, MAC and any block padding needed.
	 := len() - recordHeaderLen
	[3] = byte( >> 8)
	[4] = byte()
	.incSeq()

	return , nil
}
RecordHeaderError is returned when a TLS record header is invalid.
Msg contains a human readable string that describes the error.
RecordHeader contains the five bytes of TLS record header that triggered the error.
Conn provides the underlying net.Conn in the case that a client sent an initial handshake that didn't look like TLS. It is nil if there's already been a handshake or a TLS alert has been written to the connection.
	Conn net.Conn
}

func ( RecordHeaderError) () string { return "tls: " + .Msg }

func ( *Conn) ( net.Conn,  string) ( RecordHeaderError) {
	.Msg = 
	.Conn = 
	copy(.RecordHeader[:], .rawInput.Bytes())
	return 
}

func ( *Conn) () error {
	return .readRecordOrCCS(false)
}

func ( *Conn) () error {
	return .readRecordOrCCS(true)
}
readRecordOrCCS reads one or more TLS records from the connection and updates the record layer state. Some invariants: * c.in must be locked * c.input must be empty During the handshake one and only one of the following will happen: - c.hand grows - c.in.changeCipherSpec is called - an error is returned After the handshake one and only one of the following will happen: - c.hand grows - c.input is set - an error is returned
func ( *Conn) ( bool) error {
	if .in.err != nil {
		return .in.err
	}
	 := .handshakeComplete()
This function modifies c.rawInput, which owns the c.input memory.
	if .input.Len() != 0 {
		return .in.setErrorLocked(errors.New("tls: internal error: attempted to read record with pending application data"))
	}
	.input.Reset(nil)
Read header, payload.
RFC 8446, Section 6.1 suggests that EOF without an alertCloseNotify is an error, but popular web sites seem to do this, so we accept it if and only if at the record boundary.
		if  == io.ErrUnexpectedEOF && .rawInput.Len() == 0 {
			 = io.EOF
		}
		if ,  := .(net.Error); ! || !.Temporary() {
			.in.setErrorLocked()
		}
		return 
	}
	 := .rawInput.Bytes()[:recordHeaderLen]
	 := recordType([0])
No valid TLS record has a type of 0x80, however SSLv2 handshakes start with a uint16 length where the MSB is set and the first record is always < 256 bytes long. Therefore typ == 0x80 strongly suggests an SSLv2 client.
	if ! &&  == 0x80 {
		.sendAlert(alertProtocolVersion)
		return .in.setErrorLocked(.newRecordHeaderError(nil, "unsupported SSLv2 handshake received"))
	}

	 := uint16([1])<<8 | uint16([2])
	 := int([3])<<8 | int([4])
	if .haveVers && .vers != VersionTLS13 &&  != .vers {
		.sendAlert(alertProtocolVersion)
		 := fmt.Sprintf("received record with version %x when expecting version %x", , .vers)
		return .in.setErrorLocked(.newRecordHeaderError(nil, ))
	}
First message, be extra suspicious: this might not be a TLS client. Bail out before reading a full 'body', if possible. The current max version is 3.3 so if the version is >= 16.0, it's probably not real.
		if ( != recordTypeAlert &&  != recordTypeHandshake) ||  >= 0x1000 {
			return .in.setErrorLocked(.newRecordHeaderError(.conn, "first record does not look like a TLS handshake"))
		}
	}
	if .vers == VersionTLS13 &&  > maxCiphertextTLS13 ||  > maxCiphertext {
		.sendAlert(alertRecordOverflow)
		 := fmt.Sprintf("oversized record received with length %d", )
		return .in.setErrorLocked(.newRecordHeaderError(nil, ))
	}
	if  := .readFromUntil(.conn, recordHeaderLen+);  != nil {
		if ,  := .(net.Error); ! || !.Temporary() {
			.in.setErrorLocked()
		}
		return 
	}
Process message.
	 := .rawInput.Next(recordHeaderLen + )
	, ,  := .in.decrypt()
	if  != nil {
		return .in.setErrorLocked(.sendAlert(.(alert)))
	}
	if len() > maxPlaintext {
		return .in.setErrorLocked(.sendAlert(alertRecordOverflow))
	}
Application Data messages are always protected.
This is a state-advancing message: reset the retry count.
		.retryCount = 0
	}
Handshake messages MUST NOT be interleaved with other record types in TLS 1.3.
	if .vers == VersionTLS13 &&  != recordTypeHandshake && .hand.Len() > 0 {
		return .in.setErrorLocked(.sendAlert(alertUnexpectedMessage))
	}

	switch  {
	default:
		return .in.setErrorLocked(.sendAlert(alertUnexpectedMessage))

	case recordTypeAlert:
		if len() != 2 {
			return .in.setErrorLocked(.sendAlert(alertUnexpectedMessage))
		}
		if alert([1]) == alertCloseNotify {
			return .in.setErrorLocked(io.EOF)
		}
		if .vers == VersionTLS13 {
			return .in.setErrorLocked(&net.OpError{Op: "remote error", Err: alert([1])})
		}
		switch [0] {
Drop the record on the floor and retry.
			return .retryReadRecord()
		case alertLevelError:
			return .in.setErrorLocked(&net.OpError{Op: "remote error", Err: alert([1])})
		default:
			return .in.setErrorLocked(.sendAlert(alertUnexpectedMessage))
		}

	case recordTypeChangeCipherSpec:
		if len() != 1 || [0] != 1 {
			return .in.setErrorLocked(.sendAlert(alertDecodeError))
Handshake messages are not allowed to fragment across the CCS.
In TLS 1.3, change_cipher_spec records are ignored until the Finished. See RFC 8446, Appendix D.4. Note that according to Section 5, a server can send a ChangeCipherSpec before its ServerHello, when c.vers is still unset. That's not useful though and suspicious if the server then selects a lower protocol version, so don't allow that.
		if .vers == VersionTLS13 {
			return .retryReadRecord()
		}
		if ! {
			return .in.setErrorLocked(.sendAlert(alertUnexpectedMessage))
		}
		if  := .in.changeCipherSpec();  != nil {
			return .in.setErrorLocked(.sendAlert(.(alert)))
		}

	case recordTypeApplicationData:
		if ! ||  {
			return .in.setErrorLocked(.sendAlert(alertUnexpectedMessage))
Some OpenSSL servers send empty records in order to randomize the CBC IV. Ignore a limited number of empty records.
		if len() == 0 {
			return .retryReadRecord()
Note that data is owned by c.rawInput, following the Next call above, to avoid copying the plaintext. This is safe because c.rawInput is not read from or written to until c.input is drained.
		.input.Reset()

	case recordTypeHandshake:
		if len() == 0 ||  {
			return .in.setErrorLocked(.sendAlert(alertUnexpectedMessage))
		}
		.hand.Write()
	}

	return nil
}
retryReadRecord recurses into readRecordOrCCS to drop a non-advancing record, like a warning alert, empty application_data, or a change_cipher_spec in TLS 1.3.
func ( *Conn) ( bool) error {
	.retryCount++
	if .retryCount > maxUselessRecords {
		.sendAlert(alertUnexpectedMessage)
		return .in.setErrorLocked(errors.New("tls: too many ignored records"))
	}
	return .readRecordOrCCS()
}
atLeastReader reads from R, stopping with EOF once at least N bytes have been read. It is different from an io.LimitedReader in that it doesn't cut short the last Read call, and in that it considers an early EOF an error.
type atLeastReader struct {
	R io.Reader
	N int64
}

func ( *atLeastReader) ( []byte) (int, error) {
	if .N <= 0 {
		return 0, io.EOF
	}
	,  := .R.Read()
	.N -= int64() // won't underflow unless len(p) >= n > 9223372036854775809
	if .N > 0 &&  == io.EOF {
		return , io.ErrUnexpectedEOF
	}
	if .N <= 0 &&  == nil {
		return , io.EOF
	}
	return , 
}
readFromUntil reads from r into c.rawInput until c.rawInput contains at least n bytes or else returns an error.
func ( *Conn) ( io.Reader,  int) error {
	if .rawInput.Len() >=  {
		return nil
	}
There might be extra input waiting on the wire. Make a best effort attempt to fetch it so that it can be used in (*Conn).Read to "predict" closeNotify alerts.
	.rawInput.Grow( + bytes.MinRead)
	,  := .rawInput.ReadFrom(&atLeastReader{, int64()})
	return 
}
sendAlert sends a TLS alert message.
func ( *Conn) ( alert) error {
	switch  {
	case alertNoRenegotiation, alertCloseNotify:
		.tmp[0] = alertLevelWarning
	default:
		.tmp[0] = alertLevelError
	}
	.tmp[1] = byte()

	,  := .writeRecordLocked(recordTypeAlert, .tmp[0:2])
closeNotify is a special case in that it isn't an error.
		return 
	}

	return .out.setErrorLocked(&net.OpError{Op: "local error", Err: })
}
sendAlert sends a TLS alert message.
func ( *Conn) ( alert) error {
	.out.Lock()
	defer .out.Unlock()
	return .sendAlertLocked()
}

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).
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
)
maxPayloadSizeForWrite returns the maximum TLS payload size to use for the next application data record. There is the following trade-off: - For latency-sensitive applications, such as web browsing, each TLS record should fit in one TCP segment. - For throughput-sensitive applications, such as large file transfers, larger TLS records better amortize framing and encryption overheads. A simple heuristic that works well in practice is to use small records for the first 1MB of data, then use larger records for subsequent data, and reset back to smaller records after the connection becomes idle. See "High Performance Web Networking", Chapter 4, or: https://www.igvita.com/2013/10/24/optimizing-tls-record-size-and-buffering-latency/ In the interests of simplicity and determinism, this code does not attempt to reset the record size once the connection is idle, however.
Subtract TLS overheads to get the maximum payload size.
	 := tcpMSSEstimate - recordHeaderLen - .out.explicitNonceLen()
	if .out.cipher != nil {
		switch ciph := .out.cipher.(type) {
		case cipher.Stream:
			 -= .out.mac.Size()
		case cipher.AEAD:
			 -= .Overhead()
		case cbcMode:
The payload must fit in a multiple of blockSize, with room for at least one padding byte.
The MAC is appended before padding so affects the payload size directly.
			 -= .out.mac.Size()
		default:
			panic("unknown cipher type")
		}
	}
	if .vers == VersionTLS13 {
		-- // encrypted ContentType
	}
Allow packet growth in arithmetic progression up to max.
	 := .packetsSent
	.packetsSent++
	if  > 1000 {
		return maxPlaintext // avoid overflow in multiply below
	}

	 :=  * int(+1)
	if  > maxPlaintext {
		 = maxPlaintext
	}
	return 
}

func ( *Conn) ( []byte) (int, error) {
	if .buffering {
		.sendBuf = append(.sendBuf, ...)
		return len(), nil
	}

	,  := .conn.Write()
	.bytesSent += int64()
	return , 
}

func ( *Conn) () (int, error) {
	if len(.sendBuf) == 0 {
		return 0, nil
	}

	,  := .conn.Write(.sendBuf)
	.bytesSent += int64()
	.sendBuf = nil
	.buffering = false
	return , 
}
outBufPool pools the record-sized scratch buffers used by writeRecordLocked.
var outBufPool = sync.Pool{
	New: func() interface{} {
		return new([]byte)
	},
}
writeRecordLocked writes a TLS record with the given type and payload to the connection and updates the record layer state.
func ( *Conn) ( recordType,  []byte) (int, error) {
	 := outBufPool.Get().(*[]byte)
	 := *
You might be tempted to simplify this by just passing &outBuf to Put, but that would make the local copy of the outBuf slice header escape to the heap, causing an allocation. Instead, we keep around the pointer to the slice header returned by Get, which is already on the heap, and overwrite and return that.
		* = 
		outBufPool.Put()
	}()

	var  int
	for len() > 0 {
		 := len()
		if  := .maxPayloadSizeForWrite();  >  {
			 = 
		}

		_,  = sliceForAppend([:0], recordHeaderLen)
		[0] = byte()
		 := .vers
Some TLS servers fail if the record version is greater than TLS 1.0 for the initial ClientHello.
			 = VersionTLS10
TLS 1.3 froze the record layer version to 1.2. See RFC 8446, Section 5.1.
			 = VersionTLS12
		}
		[1] = byte( >> 8)
		[2] = byte()
		[3] = byte( >> 8)
		[4] = byte()

		var  error
		,  = .out.encrypt(, [:], .config.rand())
		if  != nil {
			return , 
		}
		if ,  := .write();  != nil {
			return , 
		}
		 += 
		 = [:]
	}

	if  == recordTypeChangeCipherSpec && .vers != VersionTLS13 {
		if  := .out.changeCipherSpec();  != nil {
			return , .sendAlertLocked(.(alert))
		}
	}

	return , nil
}
writeRecord writes a TLS record with the given type and payload to the connection and updates the record layer state.
func ( *Conn) ( recordType,  []byte) (int, error) {
	.out.Lock()
	defer .out.Unlock()

	return .writeRecordLocked(, )
}
readHandshake reads the next handshake message from the record layer.
func ( *Conn) () (interface{}, error) {
	for .hand.Len() < 4 {
		if  := .readRecord();  != nil {
			return nil, 
		}
	}

	 := .hand.Bytes()
	 := int([1])<<16 | int([2])<<8 | int([3])
	if  > maxHandshake {
		.sendAlertLocked(alertInternalError)
		return nil, .in.setErrorLocked(fmt.Errorf("tls: handshake message of length %d bytes exceeds maximum of %d bytes", , maxHandshake))
	}
	for .hand.Len() < 4+ {
		if  := .readRecord();  != nil {
			return nil, 
		}
	}
	 = .hand.Next(4 + )
	var  handshakeMessage
	switch [0] {
	case typeHelloRequest:
		 = new(helloRequestMsg)
	case typeClientHello:
		 = new(clientHelloMsg)
	case typeServerHello:
		 = new(serverHelloMsg)
	case typeNewSessionTicket:
		if .vers == VersionTLS13 {
			 = new(newSessionTicketMsgTLS13)
		} else {
			 = new(newSessionTicketMsg)
		}
	case typeCertificate:
		if .vers == VersionTLS13 {
			 = new(certificateMsgTLS13)
		} else {
			 = new(certificateMsg)
		}
	case typeCertificateRequest:
		if .vers == VersionTLS13 {
			 = new(certificateRequestMsgTLS13)
		} else {
			 = &certificateRequestMsg{
				hasSignatureAlgorithm: .vers >= VersionTLS12,
			}
		}
	case typeCertificateStatus:
		 = new(certificateStatusMsg)
	case typeServerKeyExchange:
		 = new(serverKeyExchangeMsg)
	case typeServerHelloDone:
		 = new(serverHelloDoneMsg)
	case typeClientKeyExchange:
		 = new(clientKeyExchangeMsg)
	case typeCertificateVerify:
		 = &certificateVerifyMsg{
			hasSignatureAlgorithm: .vers >= VersionTLS12,
		}
	case typeFinished:
		 = new(finishedMsg)
	case typeEncryptedExtensions:
		 = new(encryptedExtensionsMsg)
	case typeEndOfEarlyData:
		 = new(endOfEarlyDataMsg)
	case typeKeyUpdate:
		 = new(keyUpdateMsg)
	default:
		return nil, .in.setErrorLocked(.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.
	 = append([]byte(nil), ...)

	if !.unmarshal() {
		return nil, .in.setErrorLocked(.sendAlert(alertUnexpectedMessage))
	}
	return , nil
}

var (
	errShutdown = errors.New("tls: protocol is shutdown")
)
Write writes data to the connection. As Write calls Handshake, in order to prevent indefinite blocking a deadline must be set for both Read and Write before Write is called when the handshake has not yet completed. See SetDeadline, SetReadDeadline, and SetWriteDeadline.
interlock with Close below
	for {
		 := atomic.LoadInt32(&.activeCall)
		if &1 != 0 {
			return 0, net.ErrClosed
		}
		if atomic.CompareAndSwapInt32(&.activeCall, , +2) {
			break
		}
	}
	defer atomic.AddInt32(&.activeCall, -2)

	if  := .Handshake();  != nil {
		return 0, 
	}

	.out.Lock()
	defer .out.Unlock()

	if  := .out.err;  != nil {
		return 0, 
	}

	if !.handshakeComplete() {
		return 0, alertInternalError
	}

	if .closeNotifySent {
		return 0, errShutdown
	}
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 IV. 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  int
	if len() > 1 && .vers == VersionTLS10 {
		if ,  := .out.cipher.(cipher.BlockMode);  {
			,  := .writeRecordLocked(recordTypeApplicationData, [:1])
			if  != nil {
				return , .out.setErrorLocked()
			}
			,  = 1, [1:]
		}
	}

	,  := .writeRecordLocked(recordTypeApplicationData, )
	return  + , .out.setErrorLocked()
}
handleRenegotiation processes a HelloRequest handshake message.
func ( *Conn) () error {
	if .vers == VersionTLS13 {
		return errors.New("tls: internal error: unexpected renegotiation")
	}

	,  := .readHandshake()
	if  != nil {
		return 
	}

	,  := .(*helloRequestMsg)
	if ! {
		.sendAlert(alertUnexpectedMessage)
		return unexpectedMessageError(, )
	}

	if !.isClient {
		return .sendAlert(alertNoRenegotiation)
	}

	switch .config.Renegotiation {
	case RenegotiateNever:
		return .sendAlert(alertNoRenegotiation)
	case RenegotiateOnceAsClient:
		if .handshakes > 1 {
			return .sendAlert(alertNoRenegotiation)
		}
Ok.
	default:
		.sendAlert(alertInternalError)
		return errors.New("tls: unknown Renegotiation value")
	}

	.handshakeMutex.Lock()
	defer .handshakeMutex.Unlock()

	atomic.StoreUint32(&.handshakeStatus, 0)
	if .handshakeErr = .clientHandshake(); .handshakeErr == nil {
		.handshakes++
	}
	return .handshakeErr
}
handlePostHandshakeMessage processes a handshake message arrived after the handshake is complete. Up to TLS 1.2, it indicates the start of a renegotiation.
func ( *Conn) () error {
	if .vers != VersionTLS13 {
		return .handleRenegotiation()
	}

	,  := .readHandshake()
	if  != nil {
		return 
	}

	.retryCount++
	if .retryCount > maxUselessRecords {
		.sendAlert(alertUnexpectedMessage)
		return .in.setErrorLocked(errors.New("tls: too many non-advancing records"))
	}

	switch msg := .(type) {
	case *newSessionTicketMsgTLS13:
		return .handleNewSessionTicket()
	case *keyUpdateMsg:
		return .handleKeyUpdate()
	default:
		.sendAlert(alertUnexpectedMessage)
		return fmt.Errorf("tls: received unexpected handshake message of type %T", )
	}
}

func ( *Conn) ( *keyUpdateMsg) error {
	 := cipherSuiteTLS13ByID(.cipherSuite)
	if  == nil {
		return .in.setErrorLocked(.sendAlert(alertInternalError))
	}

	 := .nextTrafficSecret(.in.trafficSecret)
	.in.setTrafficSecret(, )

	if .updateRequested {
		.out.Lock()
		defer .out.Unlock()

		 := &keyUpdateMsg{}
		,  := .writeRecordLocked(recordTypeHandshake, .marshal())
Surface the error at the next write.
			.out.setErrorLocked()
			return nil
		}

		 := .nextTrafficSecret(.out.trafficSecret)
		.out.setTrafficSecret(, )
	}

	return nil
}
Read reads data from the connection. As Read calls Handshake, in order to prevent indefinite blocking a deadline must be set for both Read and Write before Read is called when the handshake has not yet completed. See SetDeadline, SetReadDeadline, and SetWriteDeadline.
func ( *Conn) ( []byte) (int, error) {
	if  := .Handshake();  != nil {
		return 0, 
	}
Put this after Handshake, in case people were calling Read(nil) for the side effect of the Handshake.
		return 0, nil
	}

	.in.Lock()
	defer .in.Unlock()

	for .input.Len() == 0 {
		if  := .readRecord();  != nil {
			return 0, 
		}
		for .hand.Len() > 0 {
			if  := .handlePostHandshakeMessage();  != nil {
				return 0, 
			}
		}
	}

	,  := .input.Read()
If a close-notify alert is waiting, read it so that we can return (n, EOF) instead of (n, nil), to signal to the HTTP response reading goroutine that the connection is now closed. This eliminates a race where the HTTP response reading goroutine would otherwise not observe the EOF until its next read, by which time a client goroutine might have already tried to reuse the HTTP connection for a new request. See https://golang.org/cl/76400046 and https://golang.org/issue/3514
	if  != 0 && .input.Len() == 0 && .rawInput.Len() > 0 &&
		recordType(.rawInput.Bytes()[0]) == recordTypeAlert {
		if  := .readRecord();  != nil {
			return ,  // will be io.EOF on closeNotify
		}
	}

	return , nil
}
Close closes the connection.
Interlock with Conn.Write above.
	var  int32
	for {
		 = atomic.LoadInt32(&.activeCall)
		if &1 != 0 {
			return net.ErrClosed
		}
		if atomic.CompareAndSwapInt32(&.activeCall, , |1) {
			break
		}
	}
io.Writer and io.Closer should not be used concurrently. If Close is called while a Write is currently in-flight, interpret that as a sign that this Close is really just being used to break the Write and/or clean up resources and avoid sending the alertCloseNotify, which may block waiting on handshakeMutex or the c.out mutex.
		return .conn.Close()
	}

	var  error
	if .handshakeComplete() {
		if  := .closeNotify();  != nil {
			 = fmt.Errorf("tls: failed to send closeNotify alert (but connection was closed anyway): %w", )
		}
	}

	if  := .conn.Close();  != nil {
		return 
	}
	return 
}

var errEarlyCloseWrite = errors.New("tls: CloseWrite called before handshake complete")
CloseWrite shuts down the writing side of the connection. It should only be called once the handshake has completed and does not call CloseWrite on the underlying connection. Most callers should just use Close.
func ( *Conn) () error {
	if !.handshakeComplete() {
		return errEarlyCloseWrite
	}

	return .closeNotify()
}

func ( *Conn) () error {
	.out.Lock()
	defer .out.Unlock()

Set a Write Deadline to prevent possibly blocking forever.
Any subsequent writes will fail.
Handshake runs the client or server handshake protocol if it has not yet been run. Most uses of this package need not call Handshake explicitly: the first Read or Write will call it automatically. For control over canceling or setting a timeout on a handshake, use the Dialer's DialContext method.
func ( *Conn) () error {
	.handshakeMutex.Lock()
	defer .handshakeMutex.Unlock()

	if  := .handshakeErr;  != nil {
		return 
	}
	if .handshakeComplete() {
		return nil
	}

	.in.Lock()
	defer .in.Unlock()

	.handshakeErr = .handshakeFn()
	if .handshakeErr == nil {
		.handshakes++
If an error occurred during the handshake try to flush the alert that might be left in the buffer.
		.flush()
	}

	if .handshakeErr == nil && !.handshakeComplete() {
		.handshakeErr = errors.New("tls: internal error: handshake should have had a result")
	}

	return .handshakeErr
}
ConnectionState returns basic TLS details about the connection.
OCSPResponse returns the stapled OCSP response from the TLS server, if any. (Only valid for client connections.)
func ( *Conn) () []byte {
	.handshakeMutex.Lock()
	defer .handshakeMutex.Unlock()

	return .ocspResponse
}
VerifyHostname checks that the peer certificate chain is valid for connecting to host. If so, it returns nil; if not, it returns an error describing the problem.
func ( *Conn) ( string) error {
	.handshakeMutex.Lock()
	defer .handshakeMutex.Unlock()
	if !.isClient {
		return errors.New("tls: VerifyHostname called on TLS server connection")
	}
	if !.handshakeComplete() {
		return errors.New("tls: handshake has not yet been performed")
	}
	if len(.verifiedChains) == 0 {
		return errors.New("tls: handshake did not verify certificate chain")
	}
	return .peerCertificates[0].VerifyHostname()
}

func ( *Conn) () bool {
	return atomic.LoadUint32(&.handshakeStatus) == 1