package tls
import (
)
type marshalingFunction func(b *cryptobyte.Builder) error
func ( marshalingFunction) ( *cryptobyte.Builder) error {
return ()
}
func ( *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
}))
}
func ( *cryptobyte.Builder, uint64) {
.AddUint32(uint32( >> 32))
.AddUint32(uint32())
}
func ( *cryptobyte.String, *uint64) bool {
var , uint32
if !.ReadUint32(&) || !.ReadUint32(&) {
return false
}
* = uint64()<<32 | uint64()
return true
}
func ( *cryptobyte.String, *[]byte) bool {
return .ReadUint8LengthPrefixed((*cryptobyte.String)())
}
func ( *cryptobyte.String, *[]byte) bool {
return .ReadUint16LengthPrefixed((*cryptobyte.String)())
}
func ( *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 []uint16
}
func ( *clientHelloMsg) ( bool) ([]byte, error) {
var cryptobyte.Builder
if len(.serverName) > 0 {
.AddUint16(extensionServerName)
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddUint8(0)
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddBytes([]byte(.serverName))
})
})
})
}
if len(.supportedPoints) > 0 && ! {
.AddUint16(extensionSupportedPoints)
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
.AddBytes(.supportedPoints)
})
})
}
if .ticketSupported && ! {
.AddUint16(extensionSessionTicket)
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddBytes(.sessionTicket)
})
}
if .secureRenegotiationSupported && ! {
.AddUint16(extensionRenegotiationInfo)
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
.AddBytes(.secureRenegotiation)
})
})
}
if .extendedMasterSecret && ! {
.AddUint16(extensionExtendedMasterSecret)
.AddUint16(0)
}
if .scts {
.AddUint16(extensionSCT)
.AddUint16(0)
}
if .earlyData {
.AddUint16(extensionEarlyData)
.AddUint16(0)
}
if .quicTransportParameters != nil {
.AddUint16(extensionQUICTransportParameters)
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddBytes(.quicTransportParameters)
})
}
if len(.encryptedClientHello) > 0 {
.AddUint16(extensionEncryptedClientHello)
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddBytes(.encryptedClientHello)
})
}
var []uint16
if .ocspStapling {
if {
= append(, extensionStatusRequest)
} else {
.AddUint16(extensionStatusRequest)
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddUint8(1)
.AddUint16(0)
.AddUint16(0)
})
}
}
if len(.supportedCurves) > 0 {
if {
= append(, extensionSupportedCurves)
} else {
.AddUint16(extensionSupportedCurves)
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
for , := range .supportedCurves {
.AddUint16(uint16())
}
})
})
}
}
if len(.supportedSignatureAlgorithms) > 0 {
if {
= append(, extensionSignatureAlgorithms)
} else {
.AddUint16(extensionSignatureAlgorithms)
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
for , := range .supportedSignatureAlgorithms {
.AddUint16(uint16())
}
})
})
}
}
if len(.supportedSignatureAlgorithmsCert) > 0 {
if {
= append(, extensionSignatureAlgorithmsCert)
} else {
.AddUint16(extensionSignatureAlgorithmsCert)
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
for , := range .supportedSignatureAlgorithmsCert {
.AddUint16(uint16())
}
})
})
}
}
if len(.alpnProtocols) > 0 {
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 {
if {
= append(, extensionSupportedVersions)
} else {
.AddUint16(extensionSupportedVersions)
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
for , := range .supportedVersions {
.AddUint16()
}
})
})
}
}
if len(.cookie) > 0 {
if {
= append(, extensionCookie)
} else {
.AddUint16(extensionCookie)
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddBytes(.cookie)
})
})
}
}
if len(.keyShares) > 0 {
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 {
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 {
.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)
}
func ( *clientHelloMsg) () ([]byte, error) {
:= 2
for , := range .pskBinders {
+= 1
+= len()
}
var []byte
if .original != nil {
= .original
} else {
var error
, = .marshal()
if != nil {
return nil,
}
}
return [:len()-], nil
}
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) ||
!.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() {
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:
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 {
return false
}
.serverName = string()
if strings.HasSuffix(.serverName, ".") {
return false
}
}
case extensionStatusRequest:
var uint8
var cryptobyte.String
if !.ReadUint8(&) ||
!.ReadUint16LengthPrefixed(&) ||
!.ReadUint16LengthPrefixed(&) {
return false
}
.ocspStapling = == statusTypeOCSP
case extensionSupportedCurves:
var cryptobyte.String
if !.ReadUint16LengthPrefixed(&) || .Empty() {
return false
}
for !.Empty() {
var uint16
if !.ReadUint16(&) {
return false
}
.supportedCurves = append(.supportedCurves, CurveID())
}
case extensionSupportedPoints:
if !readUint8LengthPrefixed(&, &.supportedPoints) ||
len(.supportedPoints) == 0 {
return false
}
case extensionSessionTicket:
.ticketSupported = true
.ReadBytes(&.sessionTicket, len())
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 extensionRenegotiationInfo:
if !readUint8LengthPrefixed(&, &.secureRenegotiation) {
return false
}
.secureRenegotiationSupported = true
case extensionExtendedMasterSecret:
.extendedMasterSecret = true
case extensionALPN:
var cryptobyte.String
if !.ReadUint16LengthPrefixed(&) || .Empty() {
return false
}
for !.Empty() {
var cryptobyte.String
if !.ReadUint8LengthPrefixed(&) || .Empty() {
return false
}
.alpnProtocols = append(.alpnProtocols, string())
}
case extensionSCT:
.scts = true
case extensionSupportedVersions:
var cryptobyte.String
if !.ReadUint8LengthPrefixed(&) || .Empty() {
return false
}
for !.Empty() {
var uint16
if !.ReadUint16(&) {
return false
}
.supportedVersions = append(.supportedVersions, )
}
case extensionCookie:
if !readUint16LengthPrefixed(&, &.cookie) ||
len(.cookie) == 0 {
return false
}
case extensionKeyShare:
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:
.earlyData = true
case extensionPSKModes:
if !readUint8LengthPrefixed(&, &.pskModes) {
return false
}
case extensionQUICTransportParameters:
.quicTransportParameters = make([]byte, len())
if !.CopyBytes(.quicTransportParameters) {
return false
}
case extensionPreSharedKey:
if !.Empty() {
return false
}
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:
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
cookie []byte
selectedGroup CurveID
}
func ( *serverHelloMsg) () ([]byte, error) {
var cryptobyte.Builder
if .ocspStapling {
.AddUint16(extensionStatusRequest)
.AddUint16(0)
}
if .ticketSupported {
.AddUint16(extensionSessionTicket)
.AddUint16(0)
}
if .secureRenegotiationSupported {
.AddUint16(extensionRenegotiationInfo)
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddUint8LengthPrefixed(func( *cryptobyte.Builder) {
.AddBytes(.secureRenegotiation)
})
})
}
if .extendedMasterSecret {
.AddUint16(extensionExtendedMasterSecret)
.AddUint16(0)
}
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) ||
!.ReadUint16(&.vers) || !.ReadBytes(&.random, 32) ||
!readUint8LengthPrefixed(&, &.sessionId) ||
!.ReadUint16(&.cipherSuite) ||
!.ReadUint8(&.compressionMethod) {
return false
}
if .Empty() {
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:
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:
if !readUint8LengthPrefixed(&, &.supportedPoints) ||
len(.supportedPoints) == 0 {
return false
}
case extensionEncryptedClientHello:
.encryptedClientHello = make([]byte, len())
if !.CopyBytes(.encryptedClientHello) {
return false
}
case extensionServerName:
if len() != 0 {
return false
}
.serverNameAck = true
default:
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 {
.AddUint16(extensionQUICTransportParameters)
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
.AddBytes(.quicTransportParameters)
})
}
if .earlyData {
.AddUint16(extensionEarlyData)
.AddUint16(0)
}
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) ||
!.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:
.earlyData = true
case extensionEncryptedClientHello:
.echRetryConfigs = make([]byte, len())
if !.CopyBytes(.echRetryConfigs) {
return false
}
default:
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) ||
!.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) ||
!.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:
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) {
.AddUint8(0)
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
if .ocspStapling {
.AddUint16(extensionStatusRequest)
.AddUint16(0)
}
if .scts {
.AddUint16(extensionSCT)
.AddUint16(0)
}
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) ||
!.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:
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
if !.ocspStapling {
.OCSPStaple = nil
}
if !.scts {
.SignedCertificateTimestamps = nil
}
marshalCertificate(, )
})
return .Bytes()
}
func ( *cryptobyte.Builder, Certificate) {
.AddUint24LengthPrefixed(func( *cryptobyte.Builder) {
for , := range .Certificate {
.AddUint24LengthPrefixed(func( *cryptobyte.Builder) {
.AddBytes()
})
.AddUint16LengthPrefixed(func( *cryptobyte.Builder) {
if > 0 {
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) ||
!.ReadUint8LengthPrefixed(&) || !.Empty() ||
!unmarshalCertificate(&, &.certificate) ||
!.Empty() {
return false
}
.scts = .certificate.SignedCertificateTimestamps != nil
.ocspStapling = .certificate.OCSPStaple != nil
return true
}
func ( *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 {
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:
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) ||
!.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 bool
certificateTypes []byte
supportedSignatureAlgorithms []SignatureScheme
certificateAuthorities [][]byte
}
func ( *certificateRequestMsg) () ([]byte, error) {
:= 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
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) {
return false
}
if .hasSignatureAlgorithm {
if !.ReadUint16((*uint16)(&.signatureAlgorithm)) {
return false
}
}
return readUint16LengthPrefixed(&, &.signature) && .Empty()
}
type newSessionTicketMsg struct {
ticket []byte
}
func ( *newSessionTicketMsg) () ([]byte, error) {
:= 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)
}
func ( handshakeMessage, transcriptHash) error {
if , := .(handshakeMessageWithOriginalBytes); {
if := .originalBytes(); != nil {
.Write(.originalBytes())
return nil
}
}
, := .marshal()
if != nil {
return
}
.Write()
return nil
}