// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tls

import (
	
	
	
	

	
)

// The marshalingFunction type is an adapter to allow the use of ordinary
// functions as cryptobyte.MarshalingValue.
type marshalingFunction func(b *cryptobyte.Builder) error

func ( marshalingFunction) ( *cryptobyte.Builder) error {
	return ()
}

// addBytesWithLength appends a sequence of bytes to the cryptobyte.Builder. If
// the length of the sequence is not the value specified, it produces an error.
func addBytesWithLength( *cryptobyte.Builder,  []byte,  int) {
	.AddValue(marshalingFunction(func( *cryptobyte.Builder) error {
		if len() !=  {
			return fmt.Errorf("invalid value length: expected %d, got %d", , len())
		}
		.AddBytes()
		return nil
	}))
}

// addUint64 appends a big-endian, 64-bit value to the cryptobyte.Builder.
func addUint64( *cryptobyte.Builder,  uint64) {
	.AddUint32(uint32( >> 32))
	.AddUint32(uint32())
}

// readUint64 decodes a big-endian, 64-bit value into out and advances over it.
// It reports whether the read was successful.
func readUint64( *cryptobyte.String,  *uint64) bool {
	var ,  uint32
	if !.ReadUint32(&) || !.ReadUint32(&) {
		return false
	}
	* = uint64()<<32 | uint64()
	return true
}

// readUint8LengthPrefixed acts like s.ReadUint8LengthPrefixed, but targets a
// []byte instead of a cryptobyte.String.
func readUint8LengthPrefixed( *cryptobyte.String,  *[]byte) bool {
	return .ReadUint8LengthPrefixed((*cryptobyte.String)())
}

// readUint16LengthPrefixed acts like s.ReadUint16LengthPrefixed, but targets a
// []byte instead of a cryptobyte.String.
func readUint16LengthPrefixed( *cryptobyte.String,  *[]byte) bool {
	return .ReadUint16LengthPrefixed((*cryptobyte.String)())
}

// readUint24LengthPrefixed acts like s.ReadUint24LengthPrefixed, but targets a
// []byte instead of a cryptobyte.String.
func readUint24LengthPrefixed( *cryptobyte.String,  *[]byte) bool {
	return .ReadUint24LengthPrefixed((*cryptobyte.String)())
}

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
	// extensions are only populated on the servers-ide of a handshake
	extensions []uint16
}

func ( *clientHelloMsg) ( bool) ([]byte, error) {
	var  cryptobyte.Builder
	if len(.serverName) > 0 {
		// RFC 6066, Section 3
		.AddUint16(extensionServerName)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				.AddUint8(0) // name_type = host_name
				.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
					.AddBytes([]byte(.serverName))
				})
			})
		})
	}
	if len(.supportedPoints) > 0 && ! {
		// RFC 4492, Section 5.1.2
		.AddUint16(extensionSupportedPoints)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
				.AddBytes(.supportedPoints)
			})
		})
	}
	if .ticketSupported && ! {
		// RFC 5077, Section 3.2
		.AddUint16(extensionSessionTicket)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddBytes(.sessionTicket)
		})
	}
	if .secureRenegotiationSupported && ! {
		// RFC 5746, Section 3.2
		.AddUint16(extensionRenegotiationInfo)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
				.AddBytes(.secureRenegotiation)
			})
		})
	}
	if .extendedMasterSecret && ! {
		// RFC 7627
		.AddUint16(extensionExtendedMasterSecret)
		.AddUint16(0) // empty extension_data
	}
	if .scts {
		// RFC 6962, Section 3.3.1
		.AddUint16(extensionSCT)
		.AddUint16(0) // empty extension_data
	}
	if .earlyData {
		// RFC 8446, Section 4.2.10
		.AddUint16(extensionEarlyData)
		.AddUint16(0) // empty extension_data
	}
	if .quicTransportParameters != nil { // marshal zero-length parameters when present
		// RFC 9001, Section 8.2
		.AddUint16(extensionQUICTransportParameters)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddBytes(.quicTransportParameters)
		})
	}
	if len(.encryptedClientHello) > 0 {
		.AddUint16(extensionEncryptedClientHello)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddBytes(.encryptedClientHello)
		})
	}
	// Note that any extension that can be compressed during ECH must be
	// contiguous. If any additional extensions are to be compressed they must
	// be added to the following block, so that they can be properly
	// decompressed on the other side.
	var  []uint16
	if .ocspStapling {
		// RFC 4366, Section 3.6
		if  {
			 = append(, extensionStatusRequest)
		} else {
			.AddUint16(extensionStatusRequest)
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				.AddUint8(1)  // status_type = ocsp
				.AddUint16(0) // empty responder_id_list
				.AddUint16(0) // empty request_extensions
			})
		}
	}
	if len(.supportedCurves) > 0 {
		// RFC 4492, sections 5.1.1 and RFC 8446, Section 4.2.7
		if  {
			 = append(, extensionSupportedCurves)
		} else {
			.AddUint16(extensionSupportedCurves)
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
					for ,  := range .supportedCurves {
						.AddUint16(uint16())
					}
				})
			})
		}
	}
	if len(.supportedSignatureAlgorithms) > 0 {
		// RFC 5246, Section 7.4.1.4.1
		if  {
			 = append(, extensionSignatureAlgorithms)
		} else {
			.AddUint16(extensionSignatureAlgorithms)
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
					for ,  := range .supportedSignatureAlgorithms {
						.AddUint16(uint16())
					}
				})
			})
		}
	}
	if len(.supportedSignatureAlgorithmsCert) > 0 {
		// RFC 8446, Section 4.2.3
		if  {
			 = append(, extensionSignatureAlgorithmsCert)
		} else {
			.AddUint16(extensionSignatureAlgorithmsCert)
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
					for ,  := range .supportedSignatureAlgorithmsCert {
						.AddUint16(uint16())
					}
				})
			})
		}
	}
	if len(.alpnProtocols) > 0 {
		// RFC 7301, Section 3.1
		if  {
			 = append(, extensionALPN)
		} else {
			.AddUint16(extensionALPN)
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
					for ,  := range .alpnProtocols {
						.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
							.AddBytes([]byte())
						})
					}
				})
			})
		}
	}
	if len(.supportedVersions) > 0 {
		// RFC 8446, Section 4.2.1
		if  {
			 = append(, extensionSupportedVersions)
		} else {
			.AddUint16(extensionSupportedVersions)
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
					for ,  := range .supportedVersions {
						.AddUint16()
					}
				})
			})
		}
	}
	if len(.cookie) > 0 {
		// RFC 8446, Section 4.2.2
		if  {
			 = append(, extensionCookie)
		} else {
			.AddUint16(extensionCookie)
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
					.AddBytes(.cookie)
				})
			})
		}
	}
	if len(.keyShares) > 0 {
		// RFC 8446, Section 4.2.8
		if  {
			 = append(, extensionKeyShare)
		} else {
			.AddUint16(extensionKeyShare)
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
					for ,  := range .keyShares {
						.AddUint16(uint16(.group))
						.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
							.AddBytes(.data)
						})
					}
				})
			})
		}
	}
	if len(.pskModes) > 0 {
		// RFC 8446, Section 4.2.9
		if  {
			 = append(, extensionPSKModes)
		} else {
			.AddUint16(extensionPSKModes)
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
					.AddBytes(.pskModes)
				})
			})
		}
	}
	if len() > 0 &&  {
		.AddUint16(extensionECHOuterExtensions)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
				for ,  := range  {
					.AddUint16()
				}
			})
		})
	}
	if len(.pskIdentities) > 0 { // pre_shared_key must be the last extension
		// RFC 8446, Section 4.2.11
		.AddUint16(extensionPreSharedKey)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				for ,  := range .pskIdentities {
					.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
						.AddBytes(.label)
					})
					.AddUint32(.obfuscatedTicketAge)
				}
			})
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				for ,  := range .pskBinders {
					.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
						.AddBytes()
					})
				}
			})
		})
	}
	,  := .Bytes()
	if  != nil {
		return nil, 
	}

	var  cryptobyte.Builder
	.AddUint8(typeClientHello)
	.AddUint24LengthPrefixed(func( *cryptobyte.Builder) {
		.AddUint16(.vers)
		addBytesWithLength(, .random, 32)
		.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
			if ! {
				.AddBytes(.sessionId)
			}
		})
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			for ,  := range .cipherSuites {
				.AddUint16()
			}
		})
		.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
			.AddBytes(.compressionMethods)
		})

		if len() > 0 {
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				.AddBytes()
			})
		}
	})

	return .Bytes()
}

func ( *clientHelloMsg) () ([]byte, error) {
	return .marshalMsg(false)
}

// marshalWithoutBinders returns the ClientHello through the
// PreSharedKeyExtension.identities field, according to RFC 8446, Section
// 4.2.11.2. Note that m.pskBinders must be set to slices of the correct length.
func ( *clientHelloMsg) () ([]byte, error) {
	 := 2 // uint16 length prefix
	for ,  := range .pskBinders {
		 += 1 // uint8 length prefix
		 += len()
	}

	var  []byte
	if .original != nil {
		 = .original
	} else {
		var  error
		,  = .marshal()
		if  != nil {
			return nil, 
		}
	}
	return [:len()-], nil
}

// updateBinders updates the m.pskBinders field. The supplied binders must have
// the same length as the current m.pskBinders.
func ( *clientHelloMsg) ( [][]byte) error {
	if len() != len(.pskBinders) {
		return errors.New("tls: internal error: pskBinders length mismatch")
	}
	for  := range .pskBinders {
		if len([]) != len(.pskBinders[]) {
			return errors.New("tls: internal error: pskBinders length mismatch")
		}
	}
	.pskBinders = 

	return nil
}

func ( *clientHelloMsg) ( []byte) bool {
	* = clientHelloMsg{original: }
	 := cryptobyte.String()

	if !.Skip(4) || // message type and uint24 length field
		!.ReadUint16(&.vers) || !.ReadBytes(&.random, 32) ||
		!readUint8LengthPrefixed(&, &.sessionId) {
		return false
	}

	var  cryptobyte.String
	if !.ReadUint16LengthPrefixed(&) {
		return false
	}
	.cipherSuites = []uint16{}
	.secureRenegotiationSupported = false
	for !.Empty() {
		var  uint16
		if !.ReadUint16(&) {
			return false
		}
		if  == scsvRenegotiation {
			.secureRenegotiationSupported = true
		}
		.cipherSuites = append(.cipherSuites, )
	}

	if !readUint8LengthPrefixed(&, &.compressionMethods) {
		return false
	}

	if .Empty() {
		// ClientHello is optionally followed by extension data
		return true
	}

	var  cryptobyte.String
	if !.ReadUint16LengthPrefixed(&) || !.Empty() {
		return false
	}

	 := make(map[uint16]bool)
	for !.Empty() {
		var  uint16
		var  cryptobyte.String
		if !.ReadUint16(&) ||
			!.ReadUint16LengthPrefixed(&) {
			return false
		}

		if [] {
			return false
		}
		[] = true
		.extensions = append(.extensions, )

		switch  {
		case extensionServerName:
			// RFC 6066, Section 3
			var  cryptobyte.String
			if !.ReadUint16LengthPrefixed(&) || .Empty() {
				return false
			}
			for !.Empty() {
				var  uint8
				var  cryptobyte.String
				if !.ReadUint8(&) ||
					!.ReadUint16LengthPrefixed(&) ||
					.Empty() {
					return false
				}
				if  != 0 {
					continue
				}
				if len(.serverName) != 0 {
					// Multiple names of the same name_type are prohibited.
					return false
				}
				.serverName = string()
				// An SNI value may not include a trailing dot.
				if strings.HasSuffix(.serverName, ".") {
					return false
				}
			}
		case extensionStatusRequest:
			// RFC 4366, Section 3.6
			var  uint8
			var  cryptobyte.String
			if !.ReadUint8(&) ||
				!.ReadUint16LengthPrefixed(&) ||
				!.ReadUint16LengthPrefixed(&) {
				return false
			}
			.ocspStapling =  == statusTypeOCSP
		case extensionSupportedCurves:
			// RFC 4492, sections 5.1.1 and RFC 8446, Section 4.2.7
			var  cryptobyte.String
			if !.ReadUint16LengthPrefixed(&) || .Empty() {
				return false
			}
			for !.Empty() {
				var  uint16
				if !.ReadUint16(&) {
					return false
				}
				.supportedCurves = append(.supportedCurves, CurveID())
			}
		case extensionSupportedPoints:
			// RFC 4492, Section 5.1.2
			if !readUint8LengthPrefixed(&, &.supportedPoints) ||
				len(.supportedPoints) == 0 {
				return false
			}
		case extensionSessionTicket:
			// RFC 5077, Section 3.2
			.ticketSupported = true
			.ReadBytes(&.sessionTicket, len())
		case extensionSignatureAlgorithms:
			// RFC 5246, Section 7.4.1.4.1
			var  cryptobyte.String
			if !.ReadUint16LengthPrefixed(&) || .Empty() {
				return false
			}
			for !.Empty() {
				var  uint16
				if !.ReadUint16(&) {
					return false
				}
				.supportedSignatureAlgorithms = append(
					.supportedSignatureAlgorithms, SignatureScheme())
			}
		case extensionSignatureAlgorithmsCert:
			// RFC 8446, Section 4.2.3
			var  cryptobyte.String
			if !.ReadUint16LengthPrefixed(&) || .Empty() {
				return false
			}
			for !.Empty() {
				var  uint16
				if !.ReadUint16(&) {
					return false
				}
				.supportedSignatureAlgorithmsCert = append(
					.supportedSignatureAlgorithmsCert, SignatureScheme())
			}
		case extensionRenegotiationInfo:
			// RFC 5746, Section 3.2
			if !readUint8LengthPrefixed(&, &.secureRenegotiation) {
				return false
			}
			.secureRenegotiationSupported = true
		case extensionExtendedMasterSecret:
			// RFC 7627
			.extendedMasterSecret = true
		case extensionALPN:
			// RFC 7301, Section 3.1
			var  cryptobyte.String
			if !.ReadUint16LengthPrefixed(&) || .Empty() {
				return false
			}
			for !.Empty() {
				var  cryptobyte.String
				if !.ReadUint8LengthPrefixed(&) || .Empty() {
					return false
				}
				.alpnProtocols = append(.alpnProtocols, string())
			}
		case extensionSCT:
			// RFC 6962, Section 3.3.1
			.scts = true
		case extensionSupportedVersions:
			// RFC 8446, Section 4.2.1
			var  cryptobyte.String
			if !.ReadUint8LengthPrefixed(&) || .Empty() {
				return false
			}
			for !.Empty() {
				var  uint16
				if !.ReadUint16(&) {
					return false
				}
				.supportedVersions = append(.supportedVersions, )
			}
		case extensionCookie:
			// RFC 8446, Section 4.2.2
			if !readUint16LengthPrefixed(&, &.cookie) ||
				len(.cookie) == 0 {
				return false
			}
		case extensionKeyShare:
			// RFC 8446, Section 4.2.8
			var  cryptobyte.String
			if !.ReadUint16LengthPrefixed(&) {
				return false
			}
			for !.Empty() {
				var  keyShare
				if !.ReadUint16((*uint16)(&.group)) ||
					!readUint16LengthPrefixed(&, &.data) ||
					len(.data) == 0 {
					return false
				}
				.keyShares = append(.keyShares, )
			}
		case extensionEarlyData:
			// RFC 8446, Section 4.2.10
			.earlyData = true
		case extensionPSKModes:
			// RFC 8446, Section 4.2.9
			if !readUint8LengthPrefixed(&, &.pskModes) {
				return false
			}
		case extensionQUICTransportParameters:
			.quicTransportParameters = make([]byte, len())
			if !.CopyBytes(.quicTransportParameters) {
				return false
			}
		case extensionPreSharedKey:
			// RFC 8446, Section 4.2.11
			if !.Empty() {
				return false // pre_shared_key must be the last extension
			}
			var  cryptobyte.String
			if !.ReadUint16LengthPrefixed(&) || .Empty() {
				return false
			}
			for !.Empty() {
				var  pskIdentity
				if !readUint16LengthPrefixed(&, &.label) ||
					!.ReadUint32(&.obfuscatedTicketAge) ||
					len(.label) == 0 {
					return false
				}
				.pskIdentities = append(.pskIdentities, )
			}
			var  cryptobyte.String
			if !.ReadUint16LengthPrefixed(&) || .Empty() {
				return false
			}
			for !.Empty() {
				var  []byte
				if !readUint8LengthPrefixed(&, &) ||
					len() == 0 {
					return false
				}
				.pskBinders = append(.pskBinders, )
			}
		case extensionEncryptedClientHello:
			if !.ReadBytes(&.encryptedClientHello, len()) {
				return false
			}
		default:
			// Ignore unknown extensions.
			continue
		}

		if !.Empty() {
			return false
		}
	}

	return true
}

func ( *clientHelloMsg) () []byte {
	return .original
}

func ( *clientHelloMsg) () *clientHelloMsg {
	return &clientHelloMsg{
		original:                         slices.Clone(.original),
		vers:                             .vers,
		random:                           slices.Clone(.random),
		sessionId:                        slices.Clone(.sessionId),
		cipherSuites:                     slices.Clone(.cipherSuites),
		compressionMethods:               slices.Clone(.compressionMethods),
		serverName:                       .serverName,
		ocspStapling:                     .ocspStapling,
		supportedCurves:                  slices.Clone(.supportedCurves),
		supportedPoints:                  slices.Clone(.supportedPoints),
		ticketSupported:                  .ticketSupported,
		sessionTicket:                    slices.Clone(.sessionTicket),
		supportedSignatureAlgorithms:     slices.Clone(.supportedSignatureAlgorithms),
		supportedSignatureAlgorithmsCert: slices.Clone(.supportedSignatureAlgorithmsCert),
		secureRenegotiationSupported:     .secureRenegotiationSupported,
		secureRenegotiation:              slices.Clone(.secureRenegotiation),
		extendedMasterSecret:             .extendedMasterSecret,
		alpnProtocols:                    slices.Clone(.alpnProtocols),
		scts:                             .scts,
		supportedVersions:                slices.Clone(.supportedVersions),
		cookie:                           slices.Clone(.cookie),
		keyShares:                        slices.Clone(.keyShares),
		earlyData:                        .earlyData,
		pskModes:                         slices.Clone(.pskModes),
		pskIdentities:                    slices.Clone(.pskIdentities),
		pskBinders:                       slices.Clone(.pskBinders),
		quicTransportParameters:          slices.Clone(.quicTransportParameters),
		encryptedClientHello:             slices.Clone(.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

	// HelloRetryRequest extensions
	cookie        []byte
	selectedGroup CurveID
}

func ( *serverHelloMsg) () ([]byte, error) {
	var  cryptobyte.Builder
	if .ocspStapling {
		.AddUint16(extensionStatusRequest)
		.AddUint16(0) // empty extension_data
	}
	if .ticketSupported {
		.AddUint16(extensionSessionTicket)
		.AddUint16(0) // empty extension_data
	}
	if .secureRenegotiationSupported {
		.AddUint16(extensionRenegotiationInfo)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
				.AddBytes(.secureRenegotiation)
			})
		})
	}
	if .extendedMasterSecret {
		.AddUint16(extensionExtendedMasterSecret)
		.AddUint16(0) // empty extension_data
	}
	if len(.alpnProtocol) > 0 {
		.AddUint16(extensionALPN)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
					.AddBytes([]byte(.alpnProtocol))
				})
			})
		})
	}
	if len(.scts) > 0 {
		.AddUint16(extensionSCT)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				for ,  := range .scts {
					.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
						.AddBytes()
					})
				}
			})
		})
	}
	if .supportedVersion != 0 {
		.AddUint16(extensionSupportedVersions)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddUint16(.supportedVersion)
		})
	}
	if .serverShare.group != 0 {
		.AddUint16(extensionKeyShare)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddUint16(uint16(.serverShare.group))
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				.AddBytes(.serverShare.data)
			})
		})
	}
	if .selectedIdentityPresent {
		.AddUint16(extensionPreSharedKey)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddUint16(.selectedIdentity)
		})
	}

	if len(.cookie) > 0 {
		.AddUint16(extensionCookie)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				.AddBytes(.cookie)
			})
		})
	}
	if .selectedGroup != 0 {
		.AddUint16(extensionKeyShare)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddUint16(uint16(.selectedGroup))
		})
	}
	if len(.supportedPoints) > 0 {
		.AddUint16(extensionSupportedPoints)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
				.AddBytes(.supportedPoints)
			})
		})
	}
	if len(.encryptedClientHello) > 0 {
		.AddUint16(extensionEncryptedClientHello)
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddBytes(.encryptedClientHello)
		})
	}
	if .serverNameAck {
		.AddUint16(extensionServerName)
		.AddUint16(0)
	}

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

	var  cryptobyte.Builder
	.AddUint8(typeServerHello)
	.AddUint24LengthPrefixed(func( *cryptobyte.Builder) {
		.AddUint16(.vers)
		addBytesWithLength(, .random, 32)
		.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
			.AddBytes(.sessionId)
		})
		.AddUint16(.cipherSuite)
		.AddUint8(.compressionMethod)

		if len() > 0 {
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				.AddBytes()
			})
		}
	})

	return .Bytes()
}

func ( *serverHelloMsg) ( []byte) bool {
	* = serverHelloMsg{original: }
	 := cryptobyte.String()

	if !.Skip(4) || // message type and uint24 length field
		!.ReadUint16(&.vers) || !.ReadBytes(&.random, 32) ||
		!readUint8LengthPrefixed(&, &.sessionId) ||
		!.ReadUint16(&.cipherSuite) ||
		!.ReadUint8(&.compressionMethod) {
		return false
	}

	if .Empty() {
		// ServerHello is optionally followed by extension data
		return true
	}

	var  cryptobyte.String
	if !.ReadUint16LengthPrefixed(&) || !.Empty() {
		return false
	}

	 := make(map[uint16]bool)
	for !.Empty() {
		var  uint16
		var  cryptobyte.String
		if !.ReadUint16(&) ||
			!.ReadUint16LengthPrefixed(&) {
			return false
		}

		if [] {
			return false
		}
		[] = true

		switch  {
		case extensionStatusRequest:
			.ocspStapling = true
		case extensionSessionTicket:
			.ticketSupported = true
		case extensionRenegotiationInfo:
			if !readUint8LengthPrefixed(&, &.secureRenegotiation) {
				return false
			}
			.secureRenegotiationSupported = true
		case extensionExtendedMasterSecret:
			.extendedMasterSecret = true
		case extensionALPN:
			var  cryptobyte.String
			if !.ReadUint16LengthPrefixed(&) || .Empty() {
				return false
			}
			var  cryptobyte.String
			if !.ReadUint8LengthPrefixed(&) ||
				.Empty() || !.Empty() {
				return false
			}
			.alpnProtocol = string()
		case extensionSCT:
			var  cryptobyte.String
			if !.ReadUint16LengthPrefixed(&) || .Empty() {
				return false
			}
			for !.Empty() {
				var  []byte
				if !readUint16LengthPrefixed(&, &) ||
					len() == 0 {
					return false
				}
				.scts = append(.scts, )
			}
		case extensionSupportedVersions:
			if !.ReadUint16(&.supportedVersion) {
				return false
			}
		case extensionCookie:
			if !readUint16LengthPrefixed(&, &.cookie) ||
				len(.cookie) == 0 {
				return false
			}
		case extensionKeyShare:
			// This extension has different formats in SH and HRR, accept either
			// and let the handshake logic decide. See RFC 8446, Section 4.2.8.
			if len() == 2 {
				if !.ReadUint16((*uint16)(&.selectedGroup)) {
					return false
				}
			} else {
				if !.ReadUint16((*uint16)(&.serverShare.group)) ||
					!readUint16LengthPrefixed(&, &.serverShare.data) {
					return false
				}
			}
		case extensionPreSharedKey:
			.selectedIdentityPresent = true
			if !.ReadUint16(&.selectedIdentity) {
				return false
			}
		case extensionSupportedPoints:
			// RFC 4492, Section 5.1.2
			if !readUint8LengthPrefixed(&, &.supportedPoints) ||
				len(.supportedPoints) == 0 {
				return false
			}
		case extensionEncryptedClientHello: // encrypted_client_hello
			.encryptedClientHello = make([]byte, len())
			if !.CopyBytes(.encryptedClientHello) {
				return false
			}
		case extensionServerName:
			if len() != 0 {
				return false
			}
			.serverNameAck = true
		default:
			// Ignore unknown extensions.
			continue
		}

		if !.Empty() {
			return false
		}
	}

	return true
}

func ( *serverHelloMsg) () []byte {
	return .original
}

type encryptedExtensionsMsg struct {
	alpnProtocol            string
	quicTransportParameters []byte
	earlyData               bool
	echRetryConfigs         []byte
}

func ( *encryptedExtensionsMsg) () ([]byte, error) {
	var  cryptobyte.Builder
	.AddUint8(typeEncryptedExtensions)
	.AddUint24LengthPrefixed(func( *cryptobyte.Builder) {
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			if len(.alpnProtocol) > 0 {
				.AddUint16(extensionALPN)
				.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
					.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
						.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
							.AddBytes([]byte(.alpnProtocol))
						})
					})
				})
			}
			if .quicTransportParameters != nil { // marshal zero-length parameters when present
				// draft-ietf-quic-tls-32, Section 8.2
				.AddUint16(extensionQUICTransportParameters)
				.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
					.AddBytes(.quicTransportParameters)
				})
			}
			if .earlyData {
				// RFC 8446, Section 4.2.10
				.AddUint16(extensionEarlyData)
				.AddUint16(0) // empty extension_data
			}
			if len(.echRetryConfigs) > 0 {
				.AddUint16(extensionEncryptedClientHello)
				.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
					.AddBytes(.echRetryConfigs)
				})
			}
		})
	})

	return .Bytes()
}

func ( *encryptedExtensionsMsg) ( []byte) bool {
	* = encryptedExtensionsMsg{}
	 := cryptobyte.String()

	var  cryptobyte.String
	if !.Skip(4) || // message type and uint24 length field
		!.ReadUint16LengthPrefixed(&) || !.Empty() {
		return false
	}

	for !.Empty() {
		var  uint16
		var  cryptobyte.String
		if !.ReadUint16(&) ||
			!.ReadUint16LengthPrefixed(&) {
			return false
		}

		switch  {
		case extensionALPN:
			var  cryptobyte.String
			if !.ReadUint16LengthPrefixed(&) || .Empty() {
				return false
			}
			var  cryptobyte.String
			if !.ReadUint8LengthPrefixed(&) ||
				.Empty() || !.Empty() {
				return false
			}
			.alpnProtocol = string()
		case extensionQUICTransportParameters:
			.quicTransportParameters = make([]byte, len())
			if !.CopyBytes(.quicTransportParameters) {
				return false
			}
		case extensionEarlyData:
			// RFC 8446, Section 4.2.10
			.earlyData = true
		case extensionEncryptedClientHello:
			.echRetryConfigs = make([]byte, len())
			if !.CopyBytes(.echRetryConfigs) {
				return false
			}
		default:
			// Ignore unknown extensions.
			continue
		}

		if !.Empty() {
			return false
		}
	}

	return true
}

type endOfEarlyDataMsg struct{}

func ( *endOfEarlyDataMsg) () ([]byte, error) {
	 := make([]byte, 4)
	[0] = typeEndOfEarlyData
	return , nil
}

func ( *endOfEarlyDataMsg) ( []byte) bool {
	return len() == 4
}

type keyUpdateMsg struct {
	updateRequested bool
}

func ( *keyUpdateMsg) () ([]byte, error) {
	var  cryptobyte.Builder
	.AddUint8(typeKeyUpdate)
	.AddUint24LengthPrefixed(func( *cryptobyte.Builder) {
		if .updateRequested {
			.AddUint8(1)
		} else {
			.AddUint8(0)
		}
	})

	return .Bytes()
}

func ( *keyUpdateMsg) ( []byte) bool {
	 := cryptobyte.String()

	var  uint8
	if !.Skip(4) || // message type and uint24 length field
		!.ReadUint8(&) || !.Empty() {
		return false
	}
	switch  {
	case 0:
		.updateRequested = false
	case 1:
		.updateRequested = true
	default:
		return false
	}
	return true
}

type newSessionTicketMsgTLS13 struct {
	lifetime     uint32
	ageAdd       uint32
	nonce        []byte
	label        []byte
	maxEarlyData uint32
}

func ( *newSessionTicketMsgTLS13) () ([]byte, error) {
	var  cryptobyte.Builder
	.AddUint8(typeNewSessionTicket)
	.AddUint24LengthPrefixed(func( *cryptobyte.Builder) {
		.AddUint32(.lifetime)
		.AddUint32(.ageAdd)
		.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
			.AddBytes(.nonce)
		})
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddBytes(.label)
		})

		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			if .maxEarlyData > 0 {
				.AddUint16(extensionEarlyData)
				.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
					.AddUint32(.maxEarlyData)
				})
			}
		})
	})

	return .Bytes()
}

func ( *newSessionTicketMsgTLS13) ( []byte) bool {
	* = newSessionTicketMsgTLS13{}
	 := cryptobyte.String()

	var  cryptobyte.String
	if !.Skip(4) || // message type and uint24 length field
		!.ReadUint32(&.lifetime) ||
		!.ReadUint32(&.ageAdd) ||
		!readUint8LengthPrefixed(&, &.nonce) ||
		!readUint16LengthPrefixed(&, &.label) ||
		!.ReadUint16LengthPrefixed(&) ||
		!.Empty() {
		return false
	}

	for !.Empty() {
		var  uint16
		var  cryptobyte.String
		if !.ReadUint16(&) ||
			!.ReadUint16LengthPrefixed(&) {
			return false
		}

		switch  {
		case extensionEarlyData:
			if !.ReadUint32(&.maxEarlyData) {
				return false
			}
		default:
			// Ignore unknown extensions.
			continue
		}

		if !.Empty() {
			return false
		}
	}

	return true
}

type certificateRequestMsgTLS13 struct {
	ocspStapling                     bool
	scts                             bool
	supportedSignatureAlgorithms     []SignatureScheme
	supportedSignatureAlgorithmsCert []SignatureScheme
	certificateAuthorities           [][]byte
}

func ( *certificateRequestMsgTLS13) () ([]byte, error) {
	var  cryptobyte.Builder
	.AddUint8(typeCertificateRequest)
	.AddUint24LengthPrefixed(func( *cryptobyte.Builder) {
		// certificate_request_context (SHALL be zero length unless used for
		// post-handshake authentication)
		.AddUint8(0)

		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			if .ocspStapling {
				.AddUint16(extensionStatusRequest)
				.AddUint16(0) // empty extension_data
			}
			if .scts {
				// RFC 8446, Section 4.4.2.1 makes no mention of
				// signed_certificate_timestamp in CertificateRequest, but
				// "Extensions in the Certificate message from the client MUST
				// correspond to extensions in the CertificateRequest message
				// from the server." and it appears in the table in Section 4.2.
				.AddUint16(extensionSCT)
				.AddUint16(0) // empty extension_data
			}
			if len(.supportedSignatureAlgorithms) > 0 {
				.AddUint16(extensionSignatureAlgorithms)
				.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
					.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
						for ,  := range .supportedSignatureAlgorithms {
							.AddUint16(uint16())
						}
					})
				})
			}
			if len(.supportedSignatureAlgorithmsCert) > 0 {
				.AddUint16(extensionSignatureAlgorithmsCert)
				.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
					.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
						for ,  := range .supportedSignatureAlgorithmsCert {
							.AddUint16(uint16())
						}
					})
				})
			}
			if len(.certificateAuthorities) > 0 {
				.AddUint16(extensionCertificateAuthorities)
				.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
					.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
						for ,  := range .certificateAuthorities {
							.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
								.AddBytes()
							})
						}
					})
				})
			}
		})
	})

	return .Bytes()
}

func ( *certificateRequestMsgTLS13) ( []byte) bool {
	* = certificateRequestMsgTLS13{}
	 := cryptobyte.String()

	var ,  cryptobyte.String
	if !.Skip(4) || // message type and uint24 length field
		!.ReadUint8LengthPrefixed(&) || !.Empty() ||
		!.ReadUint16LengthPrefixed(&) ||
		!.Empty() {
		return false
	}

	for !.Empty() {
		var  uint16
		var  cryptobyte.String
		if !.ReadUint16(&) ||
			!.ReadUint16LengthPrefixed(&) {
			return false
		}

		switch  {
		case extensionStatusRequest:
			.ocspStapling = true
		case extensionSCT:
			.scts = true
		case extensionSignatureAlgorithms:
			var  cryptobyte.String
			if !.ReadUint16LengthPrefixed(&) || .Empty() {
				return false
			}
			for !.Empty() {
				var  uint16
				if !.ReadUint16(&) {
					return false
				}
				.supportedSignatureAlgorithms = append(
					.supportedSignatureAlgorithms, SignatureScheme())
			}
		case extensionSignatureAlgorithmsCert:
			var  cryptobyte.String
			if !.ReadUint16LengthPrefixed(&) || .Empty() {
				return false
			}
			for !.Empty() {
				var  uint16
				if !.ReadUint16(&) {
					return false
				}
				.supportedSignatureAlgorithmsCert = append(
					.supportedSignatureAlgorithmsCert, SignatureScheme())
			}
		case extensionCertificateAuthorities:
			var  cryptobyte.String
			if !.ReadUint16LengthPrefixed(&) || .Empty() {
				return false
			}
			for !.Empty() {
				var  []byte
				if !readUint16LengthPrefixed(&, &) || len() == 0 {
					return false
				}
				.certificateAuthorities = append(.certificateAuthorities, )
			}
		default:
			// Ignore unknown extensions.
			continue
		}

		if !.Empty() {
			return false
		}
	}

	return true
}

type certificateMsg struct {
	certificates [][]byte
}

func ( *certificateMsg) () ([]byte, error) {
	var  int
	for ,  := range .certificates {
		 += len()
	}

	 := 3 + 3*len(.certificates) + 
	 := make([]byte, 4+)
	[0] = typeCertificate
	[1] = uint8( >> 16)
	[2] = uint8( >> 8)
	[3] = uint8()

	 :=  - 3
	[4] = uint8( >> 16)
	[5] = uint8( >> 8)
	[6] = uint8()

	 := [7:]
	for ,  := range .certificates {
		[0] = uint8(len() >> 16)
		[1] = uint8(len() >> 8)
		[2] = uint8(len())
		copy([3:], )
		 = [3+len():]
	}

	return , nil
}

func ( *certificateMsg) ( []byte) bool {
	if len() < 7 {
		return false
	}

	 := uint32([4])<<16 | uint32([5])<<8 | uint32([6])
	if uint32(len()) != +7 {
		return false
	}

	 := 0
	 := [7:]
	for  > 0 {
		if len() < 4 {
			return false
		}
		 := uint32([0])<<16 | uint32([1])<<8 | uint32([2])
		if uint32(len()) < 3+ {
			return false
		}
		 = [3+:]
		 -= 3 + 
		++
	}

	.certificates = make([][]byte, )
	 = [7:]
	for  := 0;  < ; ++ {
		 := uint32([0])<<16 | uint32([1])<<8 | uint32([2])
		.certificates[] = [3 : 3+]
		 = [3+:]
	}

	return true
}

type certificateMsgTLS13 struct {
	certificate  Certificate
	ocspStapling bool
	scts         bool
}

func ( *certificateMsgTLS13) () ([]byte, error) {
	var  cryptobyte.Builder
	.AddUint8(typeCertificate)
	.AddUint24LengthPrefixed(func( *cryptobyte.Builder) {
		.AddUint8(0) // certificate_request_context

		 := .certificate
		if !.ocspStapling {
			.OCSPStaple = nil
		}
		if !.scts {
			.SignedCertificateTimestamps = nil
		}
		marshalCertificate(, )
	})

	return .Bytes()
}

func marshalCertificate( *cryptobyte.Builder,  Certificate) {
	.AddUint24LengthPrefixed(func( *cryptobyte.Builder) {
		for ,  := range .Certificate {
			.AddUint24LengthPrefixed(func( *cryptobyte.Builder) {
				.AddBytes()
			})
			.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
				if  > 0 {
					// This library only supports OCSP and SCT for leaf certificates.
					return
				}
				if .OCSPStaple != nil {
					.AddUint16(extensionStatusRequest)
					.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
						.AddUint8(statusTypeOCSP)
						.AddUint24LengthPrefixed(func( *cryptobyte.Builder) {
							.AddBytes(.OCSPStaple)
						})
					})
				}
				if .SignedCertificateTimestamps != nil {
					.AddUint16(extensionSCT)
					.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
						.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
							for ,  := range .SignedCertificateTimestamps {
								.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
									.AddBytes()
								})
							}
						})
					})
				}
			})
		}
	})
}

func ( *certificateMsgTLS13) ( []byte) bool {
	* = certificateMsgTLS13{}
	 := cryptobyte.String()

	var  cryptobyte.String
	if !.Skip(4) || // message type and uint24 length field
		!.ReadUint8LengthPrefixed(&) || !.Empty() ||
		!unmarshalCertificate(&, &.certificate) ||
		!.Empty() {
		return false
	}

	.scts = .certificate.SignedCertificateTimestamps != nil
	.ocspStapling = .certificate.OCSPStaple != nil

	return true
}

func unmarshalCertificate( *cryptobyte.String,  *Certificate) bool {
	var  cryptobyte.String
	if !.ReadUint24LengthPrefixed(&) {
		return false
	}
	for !.Empty() {
		var  []byte
		var  cryptobyte.String
		if !readUint24LengthPrefixed(&, &) ||
			!.ReadUint16LengthPrefixed(&) {
			return false
		}
		.Certificate = append(.Certificate, )
		for !.Empty() {
			var  uint16
			var  cryptobyte.String
			if !.ReadUint16(&) ||
				!.ReadUint16LengthPrefixed(&) {
				return false
			}
			if len(.Certificate) > 1 {
				// This library only supports OCSP and SCT for leaf certificates.
				continue
			}

			switch  {
			case extensionStatusRequest:
				var  uint8
				if !.ReadUint8(&) ||  != statusTypeOCSP ||
					!readUint24LengthPrefixed(&, &.OCSPStaple) ||
					len(.OCSPStaple) == 0 {
					return false
				}
			case extensionSCT:
				var  cryptobyte.String
				if !.ReadUint16LengthPrefixed(&) || .Empty() {
					return false
				}
				for !.Empty() {
					var  []byte
					if !readUint16LengthPrefixed(&, &) ||
						len() == 0 {
						return false
					}
					.SignedCertificateTimestamps = append(
						.SignedCertificateTimestamps, )
				}
			default:
				// Ignore unknown extensions.
				continue
			}

			if !.Empty() {
				return false
			}
		}
	}
	return true
}

type serverKeyExchangeMsg struct {
	key []byte
}

func ( *serverKeyExchangeMsg) () ([]byte, error) {
	 := len(.key)
	 := make([]byte, +4)
	[0] = typeServerKeyExchange
	[1] = uint8( >> 16)
	[2] = uint8( >> 8)
	[3] = uint8()
	copy([4:], .key)

	return , nil
}

func ( *serverKeyExchangeMsg) ( []byte) bool {
	if len() < 4 {
		return false
	}
	.key = [4:]
	return true
}

type certificateStatusMsg struct {
	response []byte
}

func ( *certificateStatusMsg) () ([]byte, error) {
	var  cryptobyte.Builder
	.AddUint8(typeCertificateStatus)
	.AddUint24LengthPrefixed(func( *cryptobyte.Builder) {
		.AddUint8(statusTypeOCSP)
		.AddUint24LengthPrefixed(func( *cryptobyte.Builder) {
			.AddBytes(.response)
		})
	})

	return .Bytes()
}

func ( *certificateStatusMsg) ( []byte) bool {
	 := cryptobyte.String()

	var  uint8
	if !.Skip(4) || // message type and uint24 length field
		!.ReadUint8(&) ||  != statusTypeOCSP ||
		!readUint24LengthPrefixed(&, &.response) ||
		len(.response) == 0 || !.Empty() {
		return false
	}
	return true
}

type serverHelloDoneMsg struct{}

func ( *serverHelloDoneMsg) () ([]byte, error) {
	 := make([]byte, 4)
	[0] = typeServerHelloDone
	return , nil
}

func ( *serverHelloDoneMsg) ( []byte) bool {
	return len() == 4
}

type clientKeyExchangeMsg struct {
	ciphertext []byte
}

func ( *clientKeyExchangeMsg) () ([]byte, error) {
	 := len(.ciphertext)
	 := make([]byte, +4)
	[0] = typeClientKeyExchange
	[1] = uint8( >> 16)
	[2] = uint8( >> 8)
	[3] = uint8()
	copy([4:], .ciphertext)

	return , nil
}

func ( *clientKeyExchangeMsg) ( []byte) bool {
	if len() < 4 {
		return false
	}
	 := int([1])<<16 | int([2])<<8 | int([3])
	if  != len()-4 {
		return false
	}
	.ciphertext = [4:]
	return true
}

type finishedMsg struct {
	verifyData []byte
}

func ( *finishedMsg) () ([]byte, error) {
	var  cryptobyte.Builder
	.AddUint8(typeFinished)
	.AddUint24LengthPrefixed(func( *cryptobyte.Builder) {
		.AddBytes(.verifyData)
	})

	return .Bytes()
}

func ( *finishedMsg) ( []byte) bool {
	 := cryptobyte.String()
	return .Skip(1) &&
		readUint24LengthPrefixed(&, &.verifyData) &&
		.Empty()
}

type certificateRequestMsg struct {
	// hasSignatureAlgorithm indicates whether this message includes a list of
	// supported signature algorithms. This change was introduced with TLS 1.2.
	hasSignatureAlgorithm bool

	certificateTypes             []byte
	supportedSignatureAlgorithms []SignatureScheme
	certificateAuthorities       [][]byte
}

func ( *certificateRequestMsg) () ([]byte, error) {
	// See RFC 4346, Section 7.4.4.
	 := 1 + len(.certificateTypes) + 2
	 := 0
	for ,  := range .certificateAuthorities {
		 += 2 + len()
	}
	 += 

	if .hasSignatureAlgorithm {
		 += 2 + 2*len(.supportedSignatureAlgorithms)
	}

	 := make([]byte, 4+)
	[0] = typeCertificateRequest
	[1] = uint8( >> 16)
	[2] = uint8( >> 8)
	[3] = uint8()

	[4] = uint8(len(.certificateTypes))

	copy([5:], .certificateTypes)
	 := [5+len(.certificateTypes):]

	if .hasSignatureAlgorithm {
		 := len(.supportedSignatureAlgorithms) * 2
		[0] = uint8( >> 8)
		[1] = uint8()
		 = [2:]
		for ,  := range .supportedSignatureAlgorithms {
			[0] = uint8( >> 8)
			[1] = uint8()
			 = [2:]
		}
	}

	[0] = uint8( >> 8)
	[1] = uint8()
	 = [2:]
	for ,  := range .certificateAuthorities {
		[0] = uint8(len() >> 8)
		[1] = uint8(len())
		 = [2:]
		copy(, )
		 = [len():]
	}

	return , nil
}

func ( *certificateRequestMsg) ( []byte) bool {
	if len() < 5 {
		return false
	}

	 := uint32([1])<<16 | uint32([2])<<8 | uint32([3])
	if uint32(len())-4 !=  {
		return false
	}

	 := int([4])
	 = [5:]
	if  == 0 || len() <=  {
		return false
	}

	.certificateTypes = make([]byte, )
	if copy(.certificateTypes, ) !=  {
		return false
	}

	 = [:]

	if .hasSignatureAlgorithm {
		if len() < 2 {
			return false
		}
		 := uint16([0])<<8 | uint16([1])
		 = [2:]
		if &1 != 0 {
			return false
		}
		if len() < int() {
			return false
		}
		 :=  / 2
		.supportedSignatureAlgorithms = make([]SignatureScheme, )
		for  := range .supportedSignatureAlgorithms {
			.supportedSignatureAlgorithms[] = SignatureScheme([0])<<8 | SignatureScheme([1])
			 = [2:]
		}
	}

	if len() < 2 {
		return false
	}
	 := uint16([0])<<8 | uint16([1])
	 = [2:]
	if len() < int() {
		return false
	}
	 := make([]byte, )
	copy(, )
	 = [:]

	.certificateAuthorities = nil
	for len() > 0 {
		if len() < 2 {
			return false
		}
		 := uint16([0])<<8 | uint16([1])
		 = [2:]

		if len() < int() {
			return false
		}

		.certificateAuthorities = append(.certificateAuthorities, [:])
		 = [:]
	}

	return len() == 0
}

type certificateVerifyMsg struct {
	hasSignatureAlgorithm bool // format change introduced in TLS 1.2
	signatureAlgorithm    SignatureScheme
	signature             []byte
}

func ( *certificateVerifyMsg) () ([]byte, error) {
	var  cryptobyte.Builder
	.AddUint8(typeCertificateVerify)
	.AddUint24LengthPrefixed(func( *cryptobyte.Builder) {
		if .hasSignatureAlgorithm {
			.AddUint16(uint16(.signatureAlgorithm))
		}
		.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
			.AddBytes(.signature)
		})
	})

	return .Bytes()
}

func ( *certificateVerifyMsg) ( []byte) bool {
	 := cryptobyte.String()

	if !.Skip(4) { // message type and uint24 length field
		return false
	}
	if .hasSignatureAlgorithm {
		if !.ReadUint16((*uint16)(&.signatureAlgorithm)) {
			return false
		}
	}
	return readUint16LengthPrefixed(&, &.signature) && .Empty()
}

type newSessionTicketMsg struct {
	ticket []byte
}

func ( *newSessionTicketMsg) () ([]byte, error) {
	// See RFC 5077, Section 3.3.
	 := len(.ticket)
	 := 2 + 4 + 
	 := make([]byte, 4+)
	[0] = typeNewSessionTicket
	[1] = uint8( >> 16)
	[2] = uint8( >> 8)
	[3] = uint8()
	[8] = uint8( >> 8)
	[9] = uint8()
	copy([10:], .ticket)

	return , nil
}

func ( *newSessionTicketMsg) ( []byte) bool {
	if len() < 10 {
		return false
	}

	 := uint32([1])<<16 | uint32([2])<<8 | uint32([3])
	if uint32(len())-4 !=  {
		return false
	}

	 := int([8])<<8 + int([9])
	if len()-10 !=  {
		return false
	}

	.ticket = [10:]

	return true
}

type helloRequestMsg struct {
}

func (*helloRequestMsg) () ([]byte, error) {
	return []byte{typeHelloRequest, 0, 0, 0}, nil
}

func (*helloRequestMsg) ( []byte) bool {
	return len() == 4
}

type transcriptHash interface {
	Write([]byte) (int, error)
}

// transcriptMsg is a helper used to hash messages which are not hashed when
// they are read from, or written to, the wire. This is typically the case for
// messages which are either not sent, or need to be hashed out of order from
// when they are read/written.
//
// For most messages, the message is marshalled using their marshal method,
// since their wire representation is idempotent. For clientHelloMsg and
// serverHelloMsg, we store the original wire representation of the message and
// use that for hashing, since unmarshal/marshal are not idempotent due to
// extension ordering and other malleable fields, which may cause differences
// between what was received and what we marshal.
func transcriptMsg( handshakeMessage,  transcriptHash) error {
	if ,  := .(handshakeMessageWithOriginalBytes);  {
		if  := .originalBytes();  != nil {
			.Write(.originalBytes())
			return nil
		}
	}

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