package  tlsimport  (	"errors" 	"fmt" 	"slices" 	"strings" 	"golang.org/x/crypto/cryptobyte" )type  marshalingFunction  func (b *cryptobyte .Builder ) error func  (f  marshalingFunction ) Marshal b  *cryptobyte .Builder ) error  {	return  f (b )}func  addBytesWithLength b  *cryptobyte .Builder , v  []byte , n  int ) {	b .AddValue (marshalingFunction (func (b  *cryptobyte .Builder ) error  {		if  len (v ) != n  {			return  fmt .Errorf ("invalid value length: expected %d, got %d" , n , len (v ))		}		b .AddBytes (v )		return  nil 	}))}func  addUint64 b  *cryptobyte .Builder , v  uint64 ) {	b .AddUint32 (uint32 (v  >> 32 ))	b .AddUint32 (uint32 (v ))}func  readUint64 s  *cryptobyte .String , out  *uint64 ) bool  {	var  hi , lo  uint32 	if  !s .ReadUint32 (&hi ) || !s .ReadUint32 (&lo ) {		return  false 	}	*out  = uint64 (hi )<<32  | uint64 (lo )	return  true }func  readUint8LengthPrefixed s  *cryptobyte .String , out  *[]byte ) bool  {	return  s .ReadUint8LengthPrefixed ((*cryptobyte .String )(out ))}func  readUint16LengthPrefixed s  *cryptobyte .String , out  *[]byte ) bool  {	return  s .ReadUint16LengthPrefixed ((*cryptobyte .String )(out ))}func  readUint24LengthPrefixed s  *cryptobyte .String , out  *[]byte ) bool  {	return  s .ReadUint24LengthPrefixed ((*cryptobyte .String )(out ))}type  clientHelloMsg  struct  {	original                          []byte 	vers                              uint16 	random                            []byte 	sessionId                         []byte 	cipherSuites                      []uint16 	compressionMethods                []uint8 	serverName                        string 	ocspStapling                      bool 	supportedCurves                   []CurveID 	supportedPoints                   []uint8 	ticketSupported                   bool 	sessionTicket                     []uint8 	supportedSignatureAlgorithms      []SignatureScheme 	supportedSignatureAlgorithmsCert  []SignatureScheme 	secureRenegotiationSupported      bool 	secureRenegotiation               []byte 	extendedMasterSecret              bool 	alpnProtocols                     []string 	scts                              bool 	supportedVersions                 []uint16 	cookie                            []byte 	keyShares                         []keyShare 	earlyData                         bool 	pskModes                          []uint8 	pskIdentities                     []pskIdentity 	pskBinders                        [][]byte 	quicTransportParameters           []byte 	encryptedClientHello              []byte }func  (m  *clientHelloMsg ) marshalMsg echInner  bool ) ([]byte , error ) {	var  exts  cryptobyte .Builder 	if  len (m .serverName ) > 0  {				exts .AddUint16 (extensionServerName )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddUint8 (0 ) 				exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {					exts .AddBytes ([]byte (m .serverName ))				})			})		})	}	if  len (m .supportedPoints ) > 0  && !echInner  {				exts .AddUint16 (extensionSupportedPoints )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddUint8LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddBytes (m .supportedPoints )			})		})	}	if  m .ticketSupported  && !echInner  {				exts .AddUint16 (extensionSessionTicket )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddBytes (m .sessionTicket )		})	}	if  m .secureRenegotiationSupported  && !echInner  {				exts .AddUint16 (extensionRenegotiationInfo )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddUint8LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddBytes (m .secureRenegotiation )			})		})	}	if  m .extendedMasterSecret  && !echInner  {				exts .AddUint16 (extensionExtendedMasterSecret )		exts .AddUint16 (0 ) 	}	if  m .scts  {				exts .AddUint16 (extensionSCT )		exts .AddUint16 (0 ) 	}	if  m .earlyData  {				exts .AddUint16 (extensionEarlyData )		exts .AddUint16 (0 ) 	}	if  m .quicTransportParameters  != nil  { 				exts .AddUint16 (extensionQUICTransportParameters )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddBytes (m .quicTransportParameters )		})	}	if  len (m .encryptedClientHello ) > 0  {		exts .AddUint16 (extensionEncryptedClientHello )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddBytes (m .encryptedClientHello )		})	}		var  echOuterExts  []uint16 	if  m .ocspStapling  {				if  echInner  {			echOuterExts  = append (echOuterExts , extensionStatusRequest )		} else  {			exts .AddUint16 (extensionStatusRequest )			exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddUint8 (1 )  				exts .AddUint16 (0 ) 				exts .AddUint16 (0 ) 			})		}	}	if  len (m .supportedCurves ) > 0  {				if  echInner  {			echOuterExts  = append (echOuterExts , extensionSupportedCurves )		} else  {			exts .AddUint16 (extensionSupportedCurves )			exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {					for  _ , curve  := range  m .supportedCurves  {						exts .AddUint16 (uint16 (curve ))					}				})			})		}	}	if  len (m .supportedSignatureAlgorithms ) > 0  {				if  echInner  {			echOuterExts  = append (echOuterExts , extensionSignatureAlgorithms )		} else  {			exts .AddUint16 (extensionSignatureAlgorithms )			exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {					for  _ , sigAlgo  := range  m .supportedSignatureAlgorithms  {						exts .AddUint16 (uint16 (sigAlgo ))					}				})			})		}	}	if  len (m .supportedSignatureAlgorithmsCert ) > 0  {				if  echInner  {			echOuterExts  = append (echOuterExts , extensionSignatureAlgorithmsCert )		} else  {			exts .AddUint16 (extensionSignatureAlgorithmsCert )			exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {					for  _ , sigAlgo  := range  m .supportedSignatureAlgorithmsCert  {						exts .AddUint16 (uint16 (sigAlgo ))					}				})			})		}	}	if  len (m .alpnProtocols ) > 0  {				if  echInner  {			echOuterExts  = append (echOuterExts , extensionALPN )		} else  {			exts .AddUint16 (extensionALPN )			exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {					for  _ , proto  := range  m .alpnProtocols  {						exts .AddUint8LengthPrefixed (func (exts  *cryptobyte .Builder ) {							exts .AddBytes ([]byte (proto ))						})					}				})			})		}	}	if  len (m .supportedVersions ) > 0  {				if  echInner  {			echOuterExts  = append (echOuterExts , extensionSupportedVersions )		} else  {			exts .AddUint16 (extensionSupportedVersions )			exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddUint8LengthPrefixed (func (exts  *cryptobyte .Builder ) {					for  _ , vers  := range  m .supportedVersions  {						exts .AddUint16 (vers )					}				})			})		}	}	if  len (m .cookie ) > 0  {				if  echInner  {			echOuterExts  = append (echOuterExts , extensionCookie )		} else  {			exts .AddUint16 (extensionCookie )			exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {					exts .AddBytes (m .cookie )				})			})		}	}	if  len (m .keyShares ) > 0  {				if  echInner  {			echOuterExts  = append (echOuterExts , extensionKeyShare )		} else  {			exts .AddUint16 (extensionKeyShare )			exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {					for  _ , ks  := range  m .keyShares  {						exts .AddUint16 (uint16 (ks .group ))						exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {							exts .AddBytes (ks .data )						})					}				})			})		}	}	if  len (m .pskModes ) > 0  {				if  echInner  {			echOuterExts  = append (echOuterExts , extensionPSKModes )		} else  {			exts .AddUint16 (extensionPSKModes )			exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddUint8LengthPrefixed (func (exts  *cryptobyte .Builder ) {					exts .AddBytes (m .pskModes )				})			})		}	}	if  len (echOuterExts ) > 0  && echInner  {		exts .AddUint16 (extensionECHOuterExtensions )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddUint8LengthPrefixed (func (exts  *cryptobyte .Builder ) {				for  _ , e  := range  echOuterExts  {					exts .AddUint16 (e )				}			})		})	}	if  len (m .pskIdentities ) > 0  { 				exts .AddUint16 (extensionPreSharedKey )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {				for  _ , psk  := range  m .pskIdentities  {					exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {						exts .AddBytes (psk .label )					})					exts .AddUint32 (psk .obfuscatedTicketAge )				}			})			exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {				for  _ , binder  := range  m .pskBinders  {					exts .AddUint8LengthPrefixed (func (exts  *cryptobyte .Builder ) {						exts .AddBytes (binder )					})				}			})		})	}	extBytes , err  := exts .Bytes ()	if  err  != nil  {		return  nil , err 	}	var  b  cryptobyte .Builder 	b .AddUint8 (typeClientHello )	b .AddUint24LengthPrefixed (func (b  *cryptobyte .Builder ) {		b .AddUint16 (m .vers )		addBytesWithLength (b , m .random , 32 )		b .AddUint8LengthPrefixed (func (b  *cryptobyte .Builder ) {			if  !echInner  {				b .AddBytes (m .sessionId )			}		})		b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {			for  _ , suite  := range  m .cipherSuites  {				b .AddUint16 (suite )			}		})		b .AddUint8LengthPrefixed (func (b  *cryptobyte .Builder ) {			b .AddBytes (m .compressionMethods )		})		if  len (extBytes ) > 0  {			b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {				b .AddBytes (extBytes )			})		}	})	return  b .Bytes ()}func  (m  *clientHelloMsg ) marshal byte , error ) {	return  m .marshalMsg (false )}func  (m  *clientHelloMsg ) marshalWithoutBinders byte , error ) {	bindersLen  := 2  	for  _ , binder  := range  m .pskBinders  {		bindersLen  += 1  		bindersLen  += len (binder )	}	var  fullMessage  []byte 	if  m .original  != nil  {		fullMessage  = m .original 	} else  {		var  err  error 		fullMessage , err  = m .marshal ()		if  err  != nil  {			return  nil , err 		}	}	return  fullMessage [:len (fullMessage )-bindersLen ], nil }func  (m  *clientHelloMsg ) updateBinders pskBinders  [][]byte ) error  {	if  len (pskBinders ) != len (m .pskBinders ) {		return  errors .New ("tls: internal error: pskBinders length mismatch" )	}	for  i  := range  m .pskBinders  {		if  len (pskBinders [i ]) != len (m .pskBinders [i ]) {			return  errors .New ("tls: internal error: pskBinders length mismatch" )		}	}	m .pskBinders  = pskBinders 	return  nil }func  (m  *clientHelloMsg ) unmarshal data  []byte ) bool  {	*m  = clientHelloMsg {original : data }	s  := cryptobyte .String (data )	if  !s .Skip (4 ) || 		!s .ReadUint16 (&m .vers ) || !s .ReadBytes (&m .random , 32 ) ||		!readUint8LengthPrefixed (&s , &m .sessionId ) {		return  false 	}	var  cipherSuites  cryptobyte .String 	if  !s .ReadUint16LengthPrefixed (&cipherSuites ) {		return  false 	}	m .cipherSuites  = []uint16 {}	m .secureRenegotiationSupported  = false 	for  !cipherSuites .Empty () {		var  suite  uint16 		if  !cipherSuites .ReadUint16 (&suite ) {			return  false 		}		if  suite  == scsvRenegotiation  {			m .secureRenegotiationSupported  = true 		}		m .cipherSuites  = append (m .cipherSuites , suite )	}	if  !readUint8LengthPrefixed (&s , &m .compressionMethods ) {		return  false 	}	if  s .Empty () {				return  true 	}	var  extensions  cryptobyte .String 	if  !s .ReadUint16LengthPrefixed (&extensions ) || !s .Empty () {		return  false 	}	seenExts  := make (map [uint16 ]bool )	for  !extensions .Empty () {		var  extension  uint16 		var  extData  cryptobyte .String 		if  !extensions .ReadUint16 (&extension ) ||			!extensions .ReadUint16LengthPrefixed (&extData ) {			return  false 		}		if  seenExts [extension ] {			return  false 		}		seenExts [extension ] = true 		switch  extension  {		case  extensionServerName :						var  nameList  cryptobyte .String 			if  !extData .ReadUint16LengthPrefixed (&nameList ) || nameList .Empty () {				return  false 			}			for  !nameList .Empty () {				var  nameType  uint8 				var  serverName  cryptobyte .String 				if  !nameList .ReadUint8 (&nameType ) ||					!nameList .ReadUint16LengthPrefixed (&serverName ) ||					serverName .Empty () {					return  false 				}				if  nameType  != 0  {					continue 				}				if  len (m .serverName ) != 0  {										return  false 				}				m .serverName  = string (serverName )								if  strings .HasSuffix (m .serverName , "." ) {					return  false 				}			}		case  extensionStatusRequest :						var  statusType  uint8 			var  ignored  cryptobyte .String 			if  !extData .ReadUint8 (&statusType ) ||				!extData .ReadUint16LengthPrefixed (&ignored ) ||				!extData .ReadUint16LengthPrefixed (&ignored ) {				return  false 			}			m .ocspStapling  = statusType  == statusTypeOCSP 		case  extensionSupportedCurves :						var  curves  cryptobyte .String 			if  !extData .ReadUint16LengthPrefixed (&curves ) || curves .Empty () {				return  false 			}			for  !curves .Empty () {				var  curve  uint16 				if  !curves .ReadUint16 (&curve ) {					return  false 				}				m .supportedCurves  = append (m .supportedCurves , CurveID (curve ))			}		case  extensionSupportedPoints :						if  !readUint8LengthPrefixed (&extData , &m .supportedPoints ) ||				len (m .supportedPoints ) == 0  {				return  false 			}		case  extensionSessionTicket :						m .ticketSupported  = true 			extData .ReadBytes (&m .sessionTicket , len (extData ))		case  extensionSignatureAlgorithms :						var  sigAndAlgs  cryptobyte .String 			if  !extData .ReadUint16LengthPrefixed (&sigAndAlgs ) || sigAndAlgs .Empty () {				return  false 			}			for  !sigAndAlgs .Empty () {				var  sigAndAlg  uint16 				if  !sigAndAlgs .ReadUint16 (&sigAndAlg ) {					return  false 				}				m .supportedSignatureAlgorithms  = append (					m .supportedSignatureAlgorithms , SignatureScheme (sigAndAlg ))			}		case  extensionSignatureAlgorithmsCert :						var  sigAndAlgs  cryptobyte .String 			if  !extData .ReadUint16LengthPrefixed (&sigAndAlgs ) || sigAndAlgs .Empty () {				return  false 			}			for  !sigAndAlgs .Empty () {				var  sigAndAlg  uint16 				if  !sigAndAlgs .ReadUint16 (&sigAndAlg ) {					return  false 				}				m .supportedSignatureAlgorithmsCert  = append (					m .supportedSignatureAlgorithmsCert , SignatureScheme (sigAndAlg ))			}		case  extensionRenegotiationInfo :						if  !readUint8LengthPrefixed (&extData , &m .secureRenegotiation ) {				return  false 			}			m .secureRenegotiationSupported  = true 		case  extensionExtendedMasterSecret :						m .extendedMasterSecret  = true 		case  extensionALPN :						var  protoList  cryptobyte .String 			if  !extData .ReadUint16LengthPrefixed (&protoList ) || protoList .Empty () {				return  false 			}			for  !protoList .Empty () {				var  proto  cryptobyte .String 				if  !protoList .ReadUint8LengthPrefixed (&proto ) || proto .Empty () {					return  false 				}				m .alpnProtocols  = append (m .alpnProtocols , string (proto ))			}		case  extensionSCT :						m .scts  = true 		case  extensionSupportedVersions :						var  versList  cryptobyte .String 			if  !extData .ReadUint8LengthPrefixed (&versList ) || versList .Empty () {				return  false 			}			for  !versList .Empty () {				var  vers  uint16 				if  !versList .ReadUint16 (&vers ) {					return  false 				}				m .supportedVersions  = append (m .supportedVersions , vers )			}		case  extensionCookie :						if  !readUint16LengthPrefixed (&extData , &m .cookie ) ||				len (m .cookie ) == 0  {				return  false 			}		case  extensionKeyShare :						var  clientShares  cryptobyte .String 			if  !extData .ReadUint16LengthPrefixed (&clientShares ) {				return  false 			}			for  !clientShares .Empty () {				var  ks  keyShare 				if  !clientShares .ReadUint16 ((*uint16 )(&ks .group )) ||					!readUint16LengthPrefixed (&clientShares , &ks .data ) ||					len (ks .data ) == 0  {					return  false 				}				m .keyShares  = append (m .keyShares , ks )			}		case  extensionEarlyData :						m .earlyData  = true 		case  extensionPSKModes :						if  !readUint8LengthPrefixed (&extData , &m .pskModes ) {				return  false 			}		case  extensionQUICTransportParameters :			m .quicTransportParameters  = make ([]byte , len (extData ))			if  !extData .CopyBytes (m .quicTransportParameters ) {				return  false 			}		case  extensionPreSharedKey :						if  !extensions .Empty () {				return  false  			}			var  identities  cryptobyte .String 			if  !extData .ReadUint16LengthPrefixed (&identities ) || identities .Empty () {				return  false 			}			for  !identities .Empty () {				var  psk  pskIdentity 				if  !readUint16LengthPrefixed (&identities , &psk .label ) ||					!identities .ReadUint32 (&psk .obfuscatedTicketAge ) ||					len (psk .label ) == 0  {					return  false 				}				m .pskIdentities  = append (m .pskIdentities , psk )			}			var  binders  cryptobyte .String 			if  !extData .ReadUint16LengthPrefixed (&binders ) || binders .Empty () {				return  false 			}			for  !binders .Empty () {				var  binder  []byte 				if  !readUint8LengthPrefixed (&binders , &binder ) ||					len (binder ) == 0  {					return  false 				}				m .pskBinders  = append (m .pskBinders , binder )			}		default :						continue 		}		if  !extData .Empty () {			return  false 		}	}	return  true }func  (m  *clientHelloMsg ) originalBytes byte  {	return  m .original }func  (m  *clientHelloMsg ) clone clientHelloMsg  {	return  &clientHelloMsg {		original :                         slices .Clone (m .original ),		vers :                             m .vers ,		random :                           slices .Clone (m .random ),		sessionId :                        slices .Clone (m .sessionId ),		cipherSuites :                     slices .Clone (m .cipherSuites ),		compressionMethods :               slices .Clone (m .compressionMethods ),		serverName :                       m .serverName ,		ocspStapling :                     m .ocspStapling ,		supportedCurves :                  slices .Clone (m .supportedCurves ),		supportedPoints :                  slices .Clone (m .supportedPoints ),		ticketSupported :                  m .ticketSupported ,		sessionTicket :                    slices .Clone (m .sessionTicket ),		supportedSignatureAlgorithms :     slices .Clone (m .supportedSignatureAlgorithms ),		supportedSignatureAlgorithmsCert : slices .Clone (m .supportedSignatureAlgorithmsCert ),		secureRenegotiationSupported :     m .secureRenegotiationSupported ,		secureRenegotiation :              slices .Clone (m .secureRenegotiation ),		extendedMasterSecret :             m .extendedMasterSecret ,		alpnProtocols :                    slices .Clone (m .alpnProtocols ),		scts :                             m .scts ,		supportedVersions :                slices .Clone (m .supportedVersions ),		cookie :                           slices .Clone (m .cookie ),		keyShares :                        slices .Clone (m .keyShares ),		earlyData :                        m .earlyData ,		pskModes :                         slices .Clone (m .pskModes ),		pskIdentities :                    slices .Clone (m .pskIdentities ),		pskBinders :                       slices .Clone (m .pskBinders ),		quicTransportParameters :          slices .Clone (m .quicTransportParameters ),		encryptedClientHello :             slices .Clone (m .encryptedClientHello ),	}}type  serverHelloMsg  struct  {	original                      []byte 	vers                          uint16 	random                        []byte 	sessionId                     []byte 	cipherSuite                   uint16 	compressionMethod             uint8 	ocspStapling                  bool 	ticketSupported               bool 	secureRenegotiationSupported  bool 	secureRenegotiation           []byte 	extendedMasterSecret          bool 	alpnProtocol                  string 	scts                          [][]byte 	supportedVersion              uint16 	serverShare                   keyShare 	selectedIdentityPresent       bool 	selectedIdentity              uint16 	supportedPoints               []uint8 	encryptedClientHello          []byte 	serverNameAck                 bool 		cookie         []byte 	selectedGroup  CurveID }func  (m  *serverHelloMsg ) marshal byte , error ) {	var  exts  cryptobyte .Builder 	if  m .ocspStapling  {		exts .AddUint16 (extensionStatusRequest )		exts .AddUint16 (0 ) 	}	if  m .ticketSupported  {		exts .AddUint16 (extensionSessionTicket )		exts .AddUint16 (0 ) 	}	if  m .secureRenegotiationSupported  {		exts .AddUint16 (extensionRenegotiationInfo )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddUint8LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddBytes (m .secureRenegotiation )			})		})	}	if  m .extendedMasterSecret  {		exts .AddUint16 (extensionExtendedMasterSecret )		exts .AddUint16 (0 ) 	}	if  len (m .alpnProtocol ) > 0  {		exts .AddUint16 (extensionALPN )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddUint8LengthPrefixed (func (exts  *cryptobyte .Builder ) {					exts .AddBytes ([]byte (m .alpnProtocol ))				})			})		})	}	if  len (m .scts ) > 0  {		exts .AddUint16 (extensionSCT )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {				for  _ , sct  := range  m .scts  {					exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {						exts .AddBytes (sct )					})				}			})		})	}	if  m .supportedVersion  != 0  {		exts .AddUint16 (extensionSupportedVersions )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddUint16 (m .supportedVersion )		})	}	if  m .serverShare .group  != 0  {		exts .AddUint16 (extensionKeyShare )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddUint16 (uint16 (m .serverShare .group ))			exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddBytes (m .serverShare .data )			})		})	}	if  m .selectedIdentityPresent  {		exts .AddUint16 (extensionPreSharedKey )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddUint16 (m .selectedIdentity )		})	}	if  len (m .cookie ) > 0  {		exts .AddUint16 (extensionCookie )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddBytes (m .cookie )			})		})	}	if  m .selectedGroup  != 0  {		exts .AddUint16 (extensionKeyShare )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddUint16 (uint16 (m .selectedGroup ))		})	}	if  len (m .supportedPoints ) > 0  {		exts .AddUint16 (extensionSupportedPoints )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddUint8LengthPrefixed (func (exts  *cryptobyte .Builder ) {				exts .AddBytes (m .supportedPoints )			})		})	}	if  len (m .encryptedClientHello ) > 0  {		exts .AddUint16 (extensionEncryptedClientHello )		exts .AddUint16LengthPrefixed (func (exts  *cryptobyte .Builder ) {			exts .AddBytes (m .encryptedClientHello )		})	}	if  m .serverNameAck  {		exts .AddUint16 (extensionServerName )		exts .AddUint16 (0 )	}	extBytes , err  := exts .Bytes ()	if  err  != nil  {		return  nil , err 	}	var  b  cryptobyte .Builder 	b .AddUint8 (typeServerHello )	b .AddUint24LengthPrefixed (func (b  *cryptobyte .Builder ) {		b .AddUint16 (m .vers )		addBytesWithLength (b , m .random , 32 )		b .AddUint8LengthPrefixed (func (b  *cryptobyte .Builder ) {			b .AddBytes (m .sessionId )		})		b .AddUint16 (m .cipherSuite )		b .AddUint8 (m .compressionMethod )		if  len (extBytes ) > 0  {			b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {				b .AddBytes (extBytes )			})		}	})	return  b .Bytes ()}func  (m  *serverHelloMsg ) unmarshal data  []byte ) bool  {	*m  = serverHelloMsg {original : data }	s  := cryptobyte .String (data )	if  !s .Skip (4 ) || 		!s .ReadUint16 (&m .vers ) || !s .ReadBytes (&m .random , 32 ) ||		!readUint8LengthPrefixed (&s , &m .sessionId ) ||		!s .ReadUint16 (&m .cipherSuite ) ||		!s .ReadUint8 (&m .compressionMethod ) {		return  false 	}	if  s .Empty () {				return  true 	}	var  extensions  cryptobyte .String 	if  !s .ReadUint16LengthPrefixed (&extensions ) || !s .Empty () {		return  false 	}	seenExts  := make (map [uint16 ]bool )	for  !extensions .Empty () {		var  extension  uint16 		var  extData  cryptobyte .String 		if  !extensions .ReadUint16 (&extension ) ||			!extensions .ReadUint16LengthPrefixed (&extData ) {			return  false 		}		if  seenExts [extension ] {			return  false 		}		seenExts [extension ] = true 		switch  extension  {		case  extensionStatusRequest :			m .ocspStapling  = true 		case  extensionSessionTicket :			m .ticketSupported  = true 		case  extensionRenegotiationInfo :			if  !readUint8LengthPrefixed (&extData , &m .secureRenegotiation ) {				return  false 			}			m .secureRenegotiationSupported  = true 		case  extensionExtendedMasterSecret :			m .extendedMasterSecret  = true 		case  extensionALPN :			var  protoList  cryptobyte .String 			if  !extData .ReadUint16LengthPrefixed (&protoList ) || protoList .Empty () {				return  false 			}			var  proto  cryptobyte .String 			if  !protoList .ReadUint8LengthPrefixed (&proto ) ||				proto .Empty () || !protoList .Empty () {				return  false 			}			m .alpnProtocol  = string (proto )		case  extensionSCT :			var  sctList  cryptobyte .String 			if  !extData .ReadUint16LengthPrefixed (&sctList ) || sctList .Empty () {				return  false 			}			for  !sctList .Empty () {				var  sct  []byte 				if  !readUint16LengthPrefixed (&sctList , &sct ) ||					len (sct ) == 0  {					return  false 				}				m .scts  = append (m .scts , sct )			}		case  extensionSupportedVersions :			if  !extData .ReadUint16 (&m .supportedVersion ) {				return  false 			}		case  extensionCookie :			if  !readUint16LengthPrefixed (&extData , &m .cookie ) ||				len (m .cookie ) == 0  {				return  false 			}		case  extensionKeyShare :						if  len (extData ) == 2  {				if  !extData .ReadUint16 ((*uint16 )(&m .selectedGroup )) {					return  false 				}			} else  {				if  !extData .ReadUint16 ((*uint16 )(&m .serverShare .group )) ||					!readUint16LengthPrefixed (&extData , &m .serverShare .data ) {					return  false 				}			}		case  extensionPreSharedKey :			m .selectedIdentityPresent  = true 			if  !extData .ReadUint16 (&m .selectedIdentity ) {				return  false 			}		case  extensionSupportedPoints :						if  !readUint8LengthPrefixed (&extData , &m .supportedPoints ) ||				len (m .supportedPoints ) == 0  {				return  false 			}		case  extensionEncryptedClientHello : 			m .encryptedClientHello  = make ([]byte , len (extData ))			if  !extData .CopyBytes (m .encryptedClientHello ) {				return  false 			}		case  extensionServerName :			if  len (extData ) != 0  {				return  false 			}			m .serverNameAck  = true 		default :						continue 		}		if  !extData .Empty () {			return  false 		}	}	return  true }func  (m  *serverHelloMsg ) originalBytes byte  {	return  m .original }type  encryptedExtensionsMsg  struct  {	alpnProtocol             string 	quicTransportParameters  []byte 	earlyData                bool 	echRetryConfigs          []byte }func  (m  *encryptedExtensionsMsg ) marshal byte , error ) {	var  b  cryptobyte .Builder 	b .AddUint8 (typeEncryptedExtensions )	b .AddUint24LengthPrefixed (func (b  *cryptobyte .Builder ) {		b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {			if  len (m .alpnProtocol ) > 0  {				b .AddUint16 (extensionALPN )				b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {					b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {						b .AddUint8LengthPrefixed (func (b  *cryptobyte .Builder ) {							b .AddBytes ([]byte (m .alpnProtocol ))						})					})				})			}			if  m .quicTransportParameters  != nil  { 								b .AddUint16 (extensionQUICTransportParameters )				b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {					b .AddBytes (m .quicTransportParameters )				})			}			if  m .earlyData  {								b .AddUint16 (extensionEarlyData )				b .AddUint16 (0 ) 			}			if  len (m .echRetryConfigs ) > 0  {				b .AddUint16 (extensionEncryptedClientHello )				b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {					b .AddBytes (m .echRetryConfigs )				})			}		})	})	return  b .Bytes ()}func  (m  *encryptedExtensionsMsg ) unmarshal data  []byte ) bool  {	*m  = encryptedExtensionsMsg {}	s  := cryptobyte .String (data )	var  extensions  cryptobyte .String 	if  !s .Skip (4 ) || 		!s .ReadUint16LengthPrefixed (&extensions ) || !s .Empty () {		return  false 	}	for  !extensions .Empty () {		var  extension  uint16 		var  extData  cryptobyte .String 		if  !extensions .ReadUint16 (&extension ) ||			!extensions .ReadUint16LengthPrefixed (&extData ) {			return  false 		}		switch  extension  {		case  extensionALPN :			var  protoList  cryptobyte .String 			if  !extData .ReadUint16LengthPrefixed (&protoList ) || protoList .Empty () {				return  false 			}			var  proto  cryptobyte .String 			if  !protoList .ReadUint8LengthPrefixed (&proto ) ||				proto .Empty () || !protoList .Empty () {				return  false 			}			m .alpnProtocol  = string (proto )		case  extensionQUICTransportParameters :			m .quicTransportParameters  = make ([]byte , len (extData ))			if  !extData .CopyBytes (m .quicTransportParameters ) {				return  false 			}		case  extensionEarlyData :						m .earlyData  = true 		case  extensionEncryptedClientHello :			m .echRetryConfigs  = make ([]byte , len (extData ))			if  !extData .CopyBytes (m .echRetryConfigs ) {				return  false 			}		default :						continue 		}		if  !extData .Empty () {			return  false 		}	}	return  true }type  endOfEarlyDataMsg  struct {}func  (m  *endOfEarlyDataMsg ) marshal byte , error ) {	x  := make ([]byte , 4 )	x [0 ] = typeEndOfEarlyData 	return  x , nil }func  (m  *endOfEarlyDataMsg ) unmarshal data  []byte ) bool  {	return  len (data ) == 4 }type  keyUpdateMsg  struct  {	updateRequested  bool }func  (m  *keyUpdateMsg ) marshal byte , error ) {	var  b  cryptobyte .Builder 	b .AddUint8 (typeKeyUpdate )	b .AddUint24LengthPrefixed (func (b  *cryptobyte .Builder ) {		if  m .updateRequested  {			b .AddUint8 (1 )		} else  {			b .AddUint8 (0 )		}	})	return  b .Bytes ()}func  (m  *keyUpdateMsg ) unmarshal data  []byte ) bool  {	s  := cryptobyte .String (data )	var  updateRequested  uint8 	if  !s .Skip (4 ) || 		!s .ReadUint8 (&updateRequested ) || !s .Empty () {		return  false 	}	switch  updateRequested  {	case  0 :		m .updateRequested  = false 	case  1 :		m .updateRequested  = true 	default :		return  false 	}	return  true }type  newSessionTicketMsgTLS13  struct  {	lifetime      uint32 	ageAdd        uint32 	nonce         []byte 	label         []byte 	maxEarlyData  uint32 }func  (m  *newSessionTicketMsgTLS13 ) marshal byte , error ) {	var  b  cryptobyte .Builder 	b .AddUint8 (typeNewSessionTicket )	b .AddUint24LengthPrefixed (func (b  *cryptobyte .Builder ) {		b .AddUint32 (m .lifetime )		b .AddUint32 (m .ageAdd )		b .AddUint8LengthPrefixed (func (b  *cryptobyte .Builder ) {			b .AddBytes (m .nonce )		})		b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {			b .AddBytes (m .label )		})		b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {			if  m .maxEarlyData  > 0  {				b .AddUint16 (extensionEarlyData )				b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {					b .AddUint32 (m .maxEarlyData )				})			}		})	})	return  b .Bytes ()}func  (m  *newSessionTicketMsgTLS13 ) unmarshal data  []byte ) bool  {	*m  = newSessionTicketMsgTLS13 {}	s  := cryptobyte .String (data )	var  extensions  cryptobyte .String 	if  !s .Skip (4 ) || 		!s .ReadUint32 (&m .lifetime ) ||		!s .ReadUint32 (&m .ageAdd ) ||		!readUint8LengthPrefixed (&s , &m .nonce ) ||		!readUint16LengthPrefixed (&s , &m .label ) ||		!s .ReadUint16LengthPrefixed (&extensions ) ||		!s .Empty () {		return  false 	}	for  !extensions .Empty () {		var  extension  uint16 		var  extData  cryptobyte .String 		if  !extensions .ReadUint16 (&extension ) ||			!extensions .ReadUint16LengthPrefixed (&extData ) {			return  false 		}		switch  extension  {		case  extensionEarlyData :			if  !extData .ReadUint32 (&m .maxEarlyData ) {				return  false 			}		default :						continue 		}		if  !extData .Empty () {			return  false 		}	}	return  true }type  certificateRequestMsgTLS13  struct  {	ocspStapling                      bool 	scts                              bool 	supportedSignatureAlgorithms      []SignatureScheme 	supportedSignatureAlgorithmsCert  []SignatureScheme 	certificateAuthorities            [][]byte }func  (m  *certificateRequestMsgTLS13 ) marshal byte , error ) {	var  b  cryptobyte .Builder 	b .AddUint8 (typeCertificateRequest )	b .AddUint24LengthPrefixed (func (b  *cryptobyte .Builder ) {				b .AddUint8 (0 )		b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {			if  m .ocspStapling  {				b .AddUint16 (extensionStatusRequest )				b .AddUint16 (0 ) 			}			if  m .scts  {								b .AddUint16 (extensionSCT )				b .AddUint16 (0 ) 			}			if  len (m .supportedSignatureAlgorithms ) > 0  {				b .AddUint16 (extensionSignatureAlgorithms )				b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {					b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {						for  _ , sigAlgo  := range  m .supportedSignatureAlgorithms  {							b .AddUint16 (uint16 (sigAlgo ))						}					})				})			}			if  len (m .supportedSignatureAlgorithmsCert ) > 0  {				b .AddUint16 (extensionSignatureAlgorithmsCert )				b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {					b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {						for  _ , sigAlgo  := range  m .supportedSignatureAlgorithmsCert  {							b .AddUint16 (uint16 (sigAlgo ))						}					})				})			}			if  len (m .certificateAuthorities ) > 0  {				b .AddUint16 (extensionCertificateAuthorities )				b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {					b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {						for  _ , ca  := range  m .certificateAuthorities  {							b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {								b .AddBytes (ca )							})						}					})				})			}		})	})	return  b .Bytes ()}func  (m  *certificateRequestMsgTLS13 ) unmarshal data  []byte ) bool  {	*m  = certificateRequestMsgTLS13 {}	s  := cryptobyte .String (data )	var  context , extensions  cryptobyte .String 	if  !s .Skip (4 ) || 		!s .ReadUint8LengthPrefixed (&context ) || !context .Empty () ||		!s .ReadUint16LengthPrefixed (&extensions ) ||		!s .Empty () {		return  false 	}	for  !extensions .Empty () {		var  extension  uint16 		var  extData  cryptobyte .String 		if  !extensions .ReadUint16 (&extension ) ||			!extensions .ReadUint16LengthPrefixed (&extData ) {			return  false 		}		switch  extension  {		case  extensionStatusRequest :			m .ocspStapling  = true 		case  extensionSCT :			m .scts  = true 		case  extensionSignatureAlgorithms :			var  sigAndAlgs  cryptobyte .String 			if  !extData .ReadUint16LengthPrefixed (&sigAndAlgs ) || sigAndAlgs .Empty () {				return  false 			}			for  !sigAndAlgs .Empty () {				var  sigAndAlg  uint16 				if  !sigAndAlgs .ReadUint16 (&sigAndAlg ) {					return  false 				}				m .supportedSignatureAlgorithms  = append (					m .supportedSignatureAlgorithms , SignatureScheme (sigAndAlg ))			}		case  extensionSignatureAlgorithmsCert :			var  sigAndAlgs  cryptobyte .String 			if  !extData .ReadUint16LengthPrefixed (&sigAndAlgs ) || sigAndAlgs .Empty () {				return  false 			}			for  !sigAndAlgs .Empty () {				var  sigAndAlg  uint16 				if  !sigAndAlgs .ReadUint16 (&sigAndAlg ) {					return  false 				}				m .supportedSignatureAlgorithmsCert  = append (					m .supportedSignatureAlgorithmsCert , SignatureScheme (sigAndAlg ))			}		case  extensionCertificateAuthorities :			var  auths  cryptobyte .String 			if  !extData .ReadUint16LengthPrefixed (&auths ) || auths .Empty () {				return  false 			}			for  !auths .Empty () {				var  ca  []byte 				if  !readUint16LengthPrefixed (&auths , &ca ) || len (ca ) == 0  {					return  false 				}				m .certificateAuthorities  = append (m .certificateAuthorities , ca )			}		default :						continue 		}		if  !extData .Empty () {			return  false 		}	}	return  true }type  certificateMsg  struct  {	certificates  [][]byte }func  (m  *certificateMsg ) marshal byte , error ) {	var  i  int 	for  _ , slice  := range  m .certificates  {		i  += len (slice )	}	length  := 3  + 3 *len (m .certificates ) + i 	x  := make ([]byte , 4 +length )	x [0 ] = typeCertificate 	x [1 ] = uint8 (length  >> 16 )	x [2 ] = uint8 (length  >> 8 )	x [3 ] = uint8 (length )	certificateOctets  := length  - 3 	x [4 ] = uint8 (certificateOctets  >> 16 )	x [5 ] = uint8 (certificateOctets  >> 8 )	x [6 ] = uint8 (certificateOctets )	y  := x [7 :]	for  _ , slice  := range  m .certificates  {		y [0 ] = uint8 (len (slice ) >> 16 )		y [1 ] = uint8 (len (slice ) >> 8 )		y [2 ] = uint8 (len (slice ))		copy (y [3 :], slice )		y  = y [3 +len (slice ):]	}	return  x , nil }func  (m  *certificateMsg ) unmarshal data  []byte ) bool  {	if  len (data ) < 7  {		return  false 	}	certsLen  := uint32 (data [4 ])<<16  | uint32 (data [5 ])<<8  | uint32 (data [6 ])	if  uint32 (len (data )) != certsLen +7  {		return  false 	}	numCerts  := 0 	d  := data [7 :]	for  certsLen  > 0  {		if  len (d ) < 4  {			return  false 		}		certLen  := uint32 (d [0 ])<<16  | uint32 (d [1 ])<<8  | uint32 (d [2 ])		if  uint32 (len (d )) < 3 +certLen  {			return  false 		}		d  = d [3 +certLen :]		certsLen  -= 3  + certLen 		numCerts ++	}	m .certificates  = make ([][]byte , numCerts )	d  = data [7 :]	for  i  := 0 ; i  < numCerts ; i ++ {		certLen  := uint32 (d [0 ])<<16  | uint32 (d [1 ])<<8  | uint32 (d [2 ])		m .certificates [i ] = d [3  : 3 +certLen ]		d  = d [3 +certLen :]	}	return  true }type  certificateMsgTLS13  struct  {	certificate   Certificate 	ocspStapling  bool 	scts          bool }func  (m  *certificateMsgTLS13 ) marshal byte , error ) {	var  b  cryptobyte .Builder 	b .AddUint8 (typeCertificate )	b .AddUint24LengthPrefixed (func (b  *cryptobyte .Builder ) {		b .AddUint8 (0 ) 		certificate  := m .certificate 		if  !m .ocspStapling  {			certificate .OCSPStaple  = nil 		}		if  !m .scts  {			certificate .SignedCertificateTimestamps  = nil 		}		marshalCertificate (b , certificate )	})	return  b .Bytes ()}func  marshalCertificate b  *cryptobyte .Builder , certificate  Certificate ) {	b .AddUint24LengthPrefixed (func (b  *cryptobyte .Builder ) {		for  i , cert  := range  certificate .Certificate  {			b .AddUint24LengthPrefixed (func (b  *cryptobyte .Builder ) {				b .AddBytes (cert )			})			b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {				if  i  > 0  {										return 				}				if  certificate .OCSPStaple  != nil  {					b .AddUint16 (extensionStatusRequest )					b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {						b .AddUint8 (statusTypeOCSP )						b .AddUint24LengthPrefixed (func (b  *cryptobyte .Builder ) {							b .AddBytes (certificate .OCSPStaple )						})					})				}				if  certificate .SignedCertificateTimestamps  != nil  {					b .AddUint16 (extensionSCT )					b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {						b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {							for  _ , sct  := range  certificate .SignedCertificateTimestamps  {								b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {									b .AddBytes (sct )								})							}						})					})				}			})		}	})}func  (m  *certificateMsgTLS13 ) unmarshal data  []byte ) bool  {	*m  = certificateMsgTLS13 {}	s  := cryptobyte .String (data )	var  context  cryptobyte .String 	if  !s .Skip (4 ) || 		!s .ReadUint8LengthPrefixed (&context ) || !context .Empty () ||		!unmarshalCertificate (&s , &m .certificate ) ||		!s .Empty () {		return  false 	}	m .scts  = m .certificate .SignedCertificateTimestamps  != nil 	m .ocspStapling  = m .certificate .OCSPStaple  != nil 	return  true }func  unmarshalCertificate s  *cryptobyte .String , certificate  *Certificate ) bool  {	var  certList  cryptobyte .String 	if  !s .ReadUint24LengthPrefixed (&certList ) {		return  false 	}	for  !certList .Empty () {		var  cert  []byte 		var  extensions  cryptobyte .String 		if  !readUint24LengthPrefixed (&certList , &cert ) ||			!certList .ReadUint16LengthPrefixed (&extensions ) {			return  false 		}		certificate .Certificate  = append (certificate .Certificate , cert )		for  !extensions .Empty () {			var  extension  uint16 			var  extData  cryptobyte .String 			if  !extensions .ReadUint16 (&extension ) ||				!extensions .ReadUint16LengthPrefixed (&extData ) {				return  false 			}			if  len (certificate .Certificate ) > 1  {								continue 			}			switch  extension  {			case  extensionStatusRequest :				var  statusType  uint8 				if  !extData .ReadUint8 (&statusType ) || statusType  != statusTypeOCSP  ||					!readUint24LengthPrefixed (&extData , &certificate .OCSPStaple ) ||					len (certificate .OCSPStaple ) == 0  {					return  false 				}			case  extensionSCT :				var  sctList  cryptobyte .String 				if  !extData .ReadUint16LengthPrefixed (&sctList ) || sctList .Empty () {					return  false 				}				for  !sctList .Empty () {					var  sct  []byte 					if  !readUint16LengthPrefixed (&sctList , &sct ) ||						len (sct ) == 0  {						return  false 					}					certificate .SignedCertificateTimestamps  = append (						certificate .SignedCertificateTimestamps , sct )				}			default :								continue 			}			if  !extData .Empty () {				return  false 			}		}	}	return  true }type  serverKeyExchangeMsg  struct  {	key  []byte }func  (m  *serverKeyExchangeMsg ) marshal byte , error ) {	length  := len (m .key )	x  := make ([]byte , length +4 )	x [0 ] = typeServerKeyExchange 	x [1 ] = uint8 (length  >> 16 )	x [2 ] = uint8 (length  >> 8 )	x [3 ] = uint8 (length )	copy (x [4 :], m .key )	return  x , nil }func  (m  *serverKeyExchangeMsg ) unmarshal data  []byte ) bool  {	if  len (data ) < 4  {		return  false 	}	m .key  = data [4 :]	return  true }type  certificateStatusMsg  struct  {	response  []byte }func  (m  *certificateStatusMsg ) marshal byte , error ) {	var  b  cryptobyte .Builder 	b .AddUint8 (typeCertificateStatus )	b .AddUint24LengthPrefixed (func (b  *cryptobyte .Builder ) {		b .AddUint8 (statusTypeOCSP )		b .AddUint24LengthPrefixed (func (b  *cryptobyte .Builder ) {			b .AddBytes (m .response )		})	})	return  b .Bytes ()}func  (m  *certificateStatusMsg ) unmarshal data  []byte ) bool  {	s  := cryptobyte .String (data )	var  statusType  uint8 	if  !s .Skip (4 ) || 		!s .ReadUint8 (&statusType ) || statusType  != statusTypeOCSP  ||		!readUint24LengthPrefixed (&s , &m .response ) ||		len (m .response ) == 0  || !s .Empty () {		return  false 	}	return  true }type  serverHelloDoneMsg  struct {}func  (m  *serverHelloDoneMsg ) marshal byte , error ) {	x  := make ([]byte , 4 )	x [0 ] = typeServerHelloDone 	return  x , nil }func  (m  *serverHelloDoneMsg ) unmarshal data  []byte ) bool  {	return  len (data ) == 4 }type  clientKeyExchangeMsg  struct  {	ciphertext  []byte }func  (m  *clientKeyExchangeMsg ) marshal byte , error ) {	length  := len (m .ciphertext )	x  := make ([]byte , length +4 )	x [0 ] = typeClientKeyExchange 	x [1 ] = uint8 (length  >> 16 )	x [2 ] = uint8 (length  >> 8 )	x [3 ] = uint8 (length )	copy (x [4 :], m .ciphertext )	return  x , nil }func  (m  *clientKeyExchangeMsg ) unmarshal data  []byte ) bool  {	if  len (data ) < 4  {		return  false 	}	l  := int (data [1 ])<<16  | int (data [2 ])<<8  | int (data [3 ])	if  l  != len (data )-4  {		return  false 	}	m .ciphertext  = data [4 :]	return  true }type  finishedMsg  struct  {	verifyData  []byte }func  (m  *finishedMsg ) marshal byte , error ) {	var  b  cryptobyte .Builder 	b .AddUint8 (typeFinished )	b .AddUint24LengthPrefixed (func (b  *cryptobyte .Builder ) {		b .AddBytes (m .verifyData )	})	return  b .Bytes ()}func  (m  *finishedMsg ) unmarshal data  []byte ) bool  {	s  := cryptobyte .String (data )	return  s .Skip (1 ) &&		readUint24LengthPrefixed (&s , &m .verifyData ) &&		s .Empty ()}type  certificateRequestMsg  struct  {		hasSignatureAlgorithm  bool 	certificateTypes              []byte 	supportedSignatureAlgorithms  []SignatureScheme 	certificateAuthorities        [][]byte }func  (m  *certificateRequestMsg ) marshal byte , error ) {		length  := 1  + len (m .certificateTypes ) + 2 	casLength  := 0 	for  _ , ca  := range  m .certificateAuthorities  {		casLength  += 2  + len (ca )	}	length  += casLength 	if  m .hasSignatureAlgorithm  {		length  += 2  + 2 *len (m .supportedSignatureAlgorithms )	}	x  := make ([]byte , 4 +length )	x [0 ] = typeCertificateRequest 	x [1 ] = uint8 (length  >> 16 )	x [2 ] = uint8 (length  >> 8 )	x [3 ] = uint8 (length )	x [4 ] = uint8 (len (m .certificateTypes ))	copy (x [5 :], m .certificateTypes )	y  := x [5 +len (m .certificateTypes ):]	if  m .hasSignatureAlgorithm  {		n  := len (m .supportedSignatureAlgorithms ) * 2 		y [0 ] = uint8 (n  >> 8 )		y [1 ] = uint8 (n )		y  = y [2 :]		for  _ , sigAlgo  := range  m .supportedSignatureAlgorithms  {			y [0 ] = uint8 (sigAlgo  >> 8 )			y [1 ] = uint8 (sigAlgo )			y  = y [2 :]		}	}	y [0 ] = uint8 (casLength  >> 8 )	y [1 ] = uint8 (casLength )	y  = y [2 :]	for  _ , ca  := range  m .certificateAuthorities  {		y [0 ] = uint8 (len (ca ) >> 8 )		y [1 ] = uint8 (len (ca ))		y  = y [2 :]		copy (y , ca )		y  = y [len (ca ):]	}	return  x , nil }func  (m  *certificateRequestMsg ) unmarshal data  []byte ) bool  {	if  len (data ) < 5  {		return  false 	}	length  := uint32 (data [1 ])<<16  | uint32 (data [2 ])<<8  | uint32 (data [3 ])	if  uint32 (len (data ))-4  != length  {		return  false 	}	numCertTypes  := int (data [4 ])	data  = data [5 :]	if  numCertTypes  == 0  || len (data ) <= numCertTypes  {		return  false 	}	m .certificateTypes  = make ([]byte , numCertTypes )	if  copy (m .certificateTypes , data ) != numCertTypes  {		return  false 	}	data  = data [numCertTypes :]	if  m .hasSignatureAlgorithm  {		if  len (data ) < 2  {			return  false 		}		sigAndHashLen  := uint16 (data [0 ])<<8  | uint16 (data [1 ])		data  = data [2 :]		if  sigAndHashLen &1  != 0  {			return  false 		}		if  len (data ) < int (sigAndHashLen ) {			return  false 		}		numSigAlgos  := sigAndHashLen  / 2 		m .supportedSignatureAlgorithms  = make ([]SignatureScheme , numSigAlgos )		for  i  := range  m .supportedSignatureAlgorithms  {			m .supportedSignatureAlgorithms [i ] = SignatureScheme (data [0 ])<<8  | SignatureScheme (data [1 ])			data  = data [2 :]		}	}	if  len (data ) < 2  {		return  false 	}	casLength  := uint16 (data [0 ])<<8  | uint16 (data [1 ])	data  = data [2 :]	if  len (data ) < int (casLength ) {		return  false 	}	cas  := make ([]byte , casLength )	copy (cas , data )	data  = data [casLength :]	m .certificateAuthorities  = nil 	for  len (cas ) > 0  {		if  len (cas ) < 2  {			return  false 		}		caLen  := uint16 (cas [0 ])<<8  | uint16 (cas [1 ])		cas  = cas [2 :]		if  len (cas ) < int (caLen ) {			return  false 		}		m .certificateAuthorities  = append (m .certificateAuthorities , cas [:caLen ])		cas  = cas [caLen :]	}	return  len (data ) == 0 }type  certificateVerifyMsg  struct  {	hasSignatureAlgorithm  bool  	signatureAlgorithm     SignatureScheme 	signature              []byte }func  (m  *certificateVerifyMsg ) marshal byte , error ) {	var  b  cryptobyte .Builder 	b .AddUint8 (typeCertificateVerify )	b .AddUint24LengthPrefixed (func (b  *cryptobyte .Builder ) {		if  m .hasSignatureAlgorithm  {			b .AddUint16 (uint16 (m .signatureAlgorithm ))		}		b .AddUint16LengthPrefixed (func (b  *cryptobyte .Builder ) {			b .AddBytes (m .signature )		})	})	return  b .Bytes ()}func  (m  *certificateVerifyMsg ) unmarshal data  []byte ) bool  {	s  := cryptobyte .String (data )	if  !s .Skip (4 ) { 		return  false 	}	if  m .hasSignatureAlgorithm  {		if  !s .ReadUint16 ((*uint16 )(&m .signatureAlgorithm )) {			return  false 		}	}	return  readUint16LengthPrefixed (&s , &m .signature ) && s .Empty ()}type  newSessionTicketMsg  struct  {	ticket  []byte }func  (m  *newSessionTicketMsg ) marshal byte , error ) {		ticketLen  := len (m .ticket )	length  := 2  + 4  + ticketLen 	x  := make ([]byte , 4 +length )	x [0 ] = typeNewSessionTicket 	x [1 ] = uint8 (length  >> 16 )	x [2 ] = uint8 (length  >> 8 )	x [3 ] = uint8 (length )	x [8 ] = uint8 (ticketLen  >> 8 )	x [9 ] = uint8 (ticketLen )	copy (x [10 :], m .ticket )	return  x , nil }func  (m  *newSessionTicketMsg ) unmarshal data  []byte ) bool  {	if  len (data ) < 10  {		return  false 	}	length  := uint32 (data [1 ])<<16  | uint32 (data [2 ])<<8  | uint32 (data [3 ])	if  uint32 (len (data ))-4  != length  {		return  false 	}	ticketLen  := int (data [8 ])<<8  + int (data [9 ])	if  len (data )-10  != ticketLen  {		return  false 	}	m .ticket  = data [10 :]	return  true }type  helloRequestMsg  struct  {}func  (*helloRequestMsg ) marshal byte , error ) {	return  []byte {typeHelloRequest , 0 , 0 , 0 }, nil }func  (*helloRequestMsg ) unmarshal data  []byte ) bool  {	return  len (data ) == 4 }type  transcriptHash  interface  {	Write ([]byte ) (int , error )}func  transcriptMsg msg  handshakeMessage , h  transcriptHash ) error  {	if  msgWithOrig , ok  := msg .(handshakeMessageWithOriginalBytes ); ok  {		if  orig  := msgWithOrig .originalBytes (); orig  != nil  {			h .Write (msgWithOrig .originalBytes ())			return  nil 		}	}	data , err  := msg .marshal ()	if  err  != nil  {		return  err 	}	h .Write (data )	return  nil } The pages are generated with Golds v0.7.6 . (GOOS=linux GOARCH=amd64)
Golds  is a Go 101  project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101  (reachable from the left QR code) to get the latest news of Golds .