func configTicketKeys(c *tls.Config, configForClient *tls.Config) []ticketKey {
	if configForClient != nil {
		if configForClient.SessionTicketsDisabled {
			return nil
		}
	}
	if c.SessionTicketsDisabled {
		return nil
	}
	s := getServerSession(c)
	s.mutex.RLock()
	defer s.mutex.RUnlock()
	if len(s.autoSessionTicketKeys) > 0 && configTime(c).Sub(s.autoSessionTicketKeys[0].created) < ticketKeyRotation {
		return s.autoSessionTicketKeys
	}
	s.mutex.RUnlock()
	defer s.mutex.RLock()
	s.mutex.Lock()
	defer s.mutex.Unlock()
	if len(s.autoSessionTicketKeys) == 0 || configTime(c).Sub(s.autoSessionTicketKeys[0].created) >= ticketKeyRotation {
		var newKey [32]byte
		if _, err := io.ReadFull(configRand(c), newKey[:]); err != nil {
			panic(fmt.Sprintf("unable to generate random session ticket key: %v", err))
		}
		valid := make([]ticketKey, 0, len(s.autoSessionTicketKeys)+1)
		valid = append(valid, configTicketKeyFromBytes(c, newKey))
		for _, k := range s.autoSessionTicketKeys {
			if configTime(c).Sub(k.created) < ticketKeyLifetime {
				valid = append(valid, k)
			}
		}
		s.autoSessionTicketKeys = valid
	}
	return s.autoSessionTicketKeys
}
ticketKeys returns the ticketKeys for this connection.
If configForClient has explicitly set keys, those will
be returned. Otherwise, the keys on c will be used and
may be rotated if auto-managed.
During rotation, any expired session ticket keys are deleted from
c.sessionTicketKeys. If the session ticket key that is currently
encrypting tickets (ie. the first ticketKey in c.sessionTicketKeys)
is not fresh, then a new session ticket key will be
created and prepended to c.sessionTicketKeys.
package tls13
import (
	"container/list"
	"crypto"
	"crypto/rand"
	"crypto/sha512"
	"crypto/tls"
	"crypto/x509"
	"errors"
	"fmt"
	"io"
	"strings"
	"sync"
	"time"
)
const (
	maxPlaintext       = 16384         
	maxCiphertext      = 16384 + 2048  
	maxCiphertextTLS13 = 16384 + 256   
	recordHeaderLen    = 5             
	maxHandshake       = 65536         
	maxUselessRecords  = 16            
)
type recordType uint8
const (
	recordTypeChangeCipherSpec recordType = 20
	recordTypeAlert            recordType = 21
	recordTypeHandshake        recordType = 22
	recordTypeApplicationData  recordType = 23
)
const (
	typeHelloRequest        uint8 = 0
	typeClientHello         uint8 = 1
	typeServerHello         uint8 = 2
	typeNewSessionTicket    uint8 = 4
	typeEndOfEarlyData      uint8 = 5
	typeEncryptedExtensions uint8 = 8
	typeCertificate         uint8 = 11
	typeServerKeyExchange   uint8 = 12
	typeCertificateRequest  uint8 = 13
	typeServerHelloDone     uint8 = 14
	typeCertificateVerify   uint8 = 15
	typeClientKeyExchange   uint8 = 16
	typeFinished            uint8 = 20
	typeCertificateStatus   uint8 = 22
	typeKeyUpdate           uint8 = 24
	typeNextProtocol        uint8 = 67   
	typeMessageHash         uint8 = 254  
)
const (
	compressionNone uint8 = 0
)
const (
	extensionServerName              uint16 = 0
	extensionStatusRequest           uint16 = 5
	extensionSupportedCurves         uint16 = 10  
	extensionSupportedPoints         uint16 = 11
	extensionSignatureAlgorithms     uint16 = 13
	extensionALPN                    uint16 = 16
	extensionSCT                     uint16 = 18
	extensionSessionTicket           uint16 = 35
	extensionPreSharedKey            uint16 = 41
	extensionEarlyData               uint16 = 42
	extensionSupportedVersions       uint16 = 43
	extensionCookie                  uint16 = 44
	extensionPSKModes                uint16 = 45
	extensionCertificateAuthorities  uint16 = 47
	extensionSignatureAlgorithmsCert uint16 = 50
	extensionKeyShare                uint16 = 51
	extensionRenegotiationInfo       uint16 = 0xff01
	extensionQUICTransportParams     uint16 = 0x39
)
const (
	scsvRenegotiation uint16 = 0x00ff
)
type keyShare struct {
	group tls.CurveID
	data  []byte
}
const (
	pskModePlain uint8 = 0
	pskModeDHE   uint8 = 1
)
type pskIdentity struct {
	label               []byte
	obfuscatedTicketAge uint32
}
const (
	pointFormatUncompressed uint8 = 0
)
const (
	statusTypeOCSP uint8 = 1
)
const (
	certTypeRSASign   = 1
	certTypeECDSASign = 64  
)
const (
	signaturePKCS1v15 uint8 = iota + 225
	signatureRSAPSS
	signatureECDSA
	signatureEd25519
)
var directSigning crypto.Hash = 0
var supportedSignatureAlgorithms = []tls.SignatureScheme{
	tls.PSSWithSHA256,
	tls.ECDSAWithP256AndSHA256,
	tls.Ed25519,
	tls.PSSWithSHA384,
	tls.PSSWithSHA512,
	tls.PKCS1WithSHA256,
	tls.PKCS1WithSHA384,
	tls.PKCS1WithSHA512,
	tls.ECDSAWithP384AndSHA384,
	tls.ECDSAWithP521AndSHA512,
	tls.PKCS1WithSHA1,
	tls.ECDSAWithSHA1,
}
var helloRetryRequestRandom = []byte{  
	0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
	0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
	0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
	0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C,
}
const (
	downgradeCanaryTLS12 = "DOWNGRD\x01"
	downgradeCanaryTLS11 = "DOWNGRD\x00"
)
func requiresClientCert(c tls.ClientAuthType) bool {
	switch c {
	case tls.RequireAnyClientCert, tls.RequireAndVerifyClientCert:
		return true
	default:
		return false
	}
}
type ClientSessionState struct {
	sessionTicket      []uint8                
	vers               uint16                 
	cipherSuite        uint16                 
	masterSecret       []byte                 
	serverCertificates []*x509.Certificate    
	verifiedChains     [][]*x509.Certificate  
	receivedAt         time.Time              
	ocspResponse       []byte                 
	scts               [][]byte               
	nonce  []byte     
	useBy  time.Time  
	ageAdd uint32     
}
type ClientSessionCache interface {
	GetClientSession(sessionKey string) (session *ClientSessionState, ok bool)
	PutClientSession(sessionKey string, cs *ClientSessionState)
}
const (
	ticketKeyNameLen = 16
	ticketKeyLifetime = 7 * 24 * time.Hour  
	ticketKeyRotation = 24 * time.Hour
)
type ticketKey struct {
	keyName [ticketKeyNameLen]byte
	aesKey  [16]byte
	hmacKey [16]byte
	created time.Time
}
func configTicketKeyFromBytes(c *tls.Config, b [32]byte) (key ticketKey) {
	hashed := sha512.Sum512(b[:])
	copy(key.keyName[:], hashed[:ticketKeyNameLen])
	copy(key.aesKey[:], hashed[ticketKeyNameLen:ticketKeyNameLen+16])
	copy(key.hmacKey[:], hashed[ticketKeyNameLen+16:ticketKeyNameLen+32])
	key.created = configTime(c)
	return key
}
const maxSessionTicketLifetime = 7 * 24 * time.Hour