mirror of
https://github.com/refraction-networking/utls.git
synced 2025-04-03 20:17:36 +03:00
crypto/tls: replace all usages of BytesOrPanic
Message marshalling makes use of BytesOrPanic a lot, under the
assumption that it will never panic. This assumption was incorrect, and
specifically crafted handshakes could trigger panics. Rather than just
surgically replacing the usages of BytesOrPanic in paths that could
panic, replace all usages of it with proper error returns in case there
are other ways of triggering panics which we didn't find.
In one specific case, the tree routed by expandLabel, we replace the
usage of BytesOrPanic, but retain a panic. This function already
explicitly panicked elsewhere, and returning an error from it becomes
rather painful because it requires changing a large number of APIs.
The marshalling is unlikely to ever panic, as the inputs are all either
fixed length, or already limited to the sizes required. If it were to
panic, it'd likely only be during development. A close inspection shows
no paths for a user to cause a panic currently.
This patches ends up being rather large, since it requires routing
errors back through functions which previously had no error returns.
Where possible I've tried to use helpers that reduce the verbosity
of frequently repeated stanzas, and to make the diffs as minimal as
possible.
Thanks to Marten Seemann for reporting this issue.
Fixes #58001
Fixes CVE-2022-41724
Change-Id: Ieb55867ef0a3e1e867b33f09421932510cb58851
Reviewed-on: 1679436
Reviewed-by: Julie Qiu <julieqiu@google.com>
TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
Run-TryBot: Roland Shoemaker <bracewell@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/468125
Run-TryBot: Michael Pratt <mpratt@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Michael Pratt <mpratt@google.com>
This commit is contained in:
parent
58e7190673
commit
ba1a41d66f
13 changed files with 657 additions and 503 deletions
|
@ -5,6 +5,7 @@
|
|||
package tls
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
|
@ -94,9 +95,181 @@ type clientHelloMsg struct {
|
|||
pskBinders [][]byte
|
||||
}
|
||||
|
||||
func (m *clientHelloMsg) marshal() []byte {
|
||||
func (m *clientHelloMsg) marshal() ([]byte, error) {
|
||||
if m.raw != nil {
|
||||
return m.raw
|
||||
return m.raw, nil
|
||||
}
|
||||
|
||||
var exts cryptobyte.Builder
|
||||
if len(m.serverName) > 0 {
|
||||
// RFC 6066, Section 3
|
||||
exts.AddUint16(extensionServerName)
|
||||
exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
|
||||
exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
|
||||
exts.AddUint8(0) // name_type = host_name
|
||||
exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
|
||||
exts.AddBytes([]byte(m.serverName))
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
if m.ocspStapling {
|
||||
// RFC 4366, Section 3.6
|
||||
exts.AddUint16(extensionStatusRequest)
|
||||
exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
|
||||
exts.AddUint8(1) // status_type = ocsp
|
||||
exts.AddUint16(0) // empty responder_id_list
|
||||
exts.AddUint16(0) // empty request_extensions
|
||||
})
|
||||
}
|
||||
if len(m.supportedCurves) > 0 {
|
||||
// RFC 4492, sections 5.1.1 and RFC 8446, Section 4.2.7
|
||||
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.supportedPoints) > 0 {
|
||||
// RFC 4492, Section 5.1.2
|
||||
exts.AddUint16(extensionSupportedPoints)
|
||||
exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
|
||||
exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) {
|
||||
exts.AddBytes(m.supportedPoints)
|
||||
})
|
||||
})
|
||||
}
|
||||
if m.ticketSupported {
|
||||
// RFC 5077, Section 3.2
|
||||
exts.AddUint16(extensionSessionTicket)
|
||||
exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
|
||||
exts.AddBytes(m.sessionTicket)
|
||||
})
|
||||
}
|
||||
if len(m.supportedSignatureAlgorithms) > 0 {
|
||||
// RFC 5246, Section 7.4.1.4.1
|
||||
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 {
|
||||
// RFC 8446, Section 4.2.3
|
||||
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 m.secureRenegotiationSupported {
|
||||
// RFC 5746, Section 3.2
|
||||
exts.AddUint16(extensionRenegotiationInfo)
|
||||
exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
|
||||
exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) {
|
||||
exts.AddBytes(m.secureRenegotiation)
|
||||
})
|
||||
})
|
||||
}
|
||||
if len(m.alpnProtocols) > 0 {
|
||||
// RFC 7301, Section 3.1
|
||||
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 m.scts {
|
||||
// RFC 6962, Section 3.3.1
|
||||
exts.AddUint16(extensionSCT)
|
||||
exts.AddUint16(0) // empty extension_data
|
||||
}
|
||||
if len(m.supportedVersions) > 0 {
|
||||
// RFC 8446, Section 4.2.1
|
||||
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 {
|
||||
// RFC 8446, Section 4.2.2
|
||||
exts.AddUint16(extensionCookie)
|
||||
exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
|
||||
exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
|
||||
exts.AddBytes(m.cookie)
|
||||
})
|
||||
})
|
||||
}
|
||||
if len(m.keyShares) > 0 {
|
||||
// RFC 8446, Section 4.2.8
|
||||
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 m.earlyData {
|
||||
// RFC 8446, Section 4.2.10
|
||||
exts.AddUint16(extensionEarlyData)
|
||||
exts.AddUint16(0) // empty extension_data
|
||||
}
|
||||
if len(m.pskModes) > 0 {
|
||||
// RFC 8446, Section 4.2.9
|
||||
exts.AddUint16(extensionPSKModes)
|
||||
exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
|
||||
exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) {
|
||||
exts.AddBytes(m.pskModes)
|
||||
})
|
||||
})
|
||||
}
|
||||
if len(m.pskIdentities) > 0 { // pre_shared_key must be the last extension
|
||||
// RFC 8446, Section 4.2.11
|
||||
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
|
||||
|
@ -116,219 +289,53 @@ func (m *clientHelloMsg) marshal() []byte {
|
|||
b.AddBytes(m.compressionMethods)
|
||||
})
|
||||
|
||||
// If extensions aren't present, omit them.
|
||||
var extensionsPresent bool
|
||||
bWithoutExtensions := *b
|
||||
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
if len(m.serverName) > 0 {
|
||||
// RFC 6066, Section 3
|
||||
b.AddUint16(extensionServerName)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint8(0) // name_type = host_name
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes([]byte(m.serverName))
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
if m.ocspStapling {
|
||||
// RFC 4366, Section 3.6
|
||||
b.AddUint16(extensionStatusRequest)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint8(1) // status_type = ocsp
|
||||
b.AddUint16(0) // empty responder_id_list
|
||||
b.AddUint16(0) // empty request_extensions
|
||||
})
|
||||
}
|
||||
if len(m.supportedCurves) > 0 {
|
||||
// RFC 4492, sections 5.1.1 and RFC 8446, Section 4.2.7
|
||||
b.AddUint16(extensionSupportedCurves)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
for _, curve := range m.supportedCurves {
|
||||
b.AddUint16(uint16(curve))
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
if len(m.supportedPoints) > 0 {
|
||||
// RFC 4492, Section 5.1.2
|
||||
b.AddUint16(extensionSupportedPoints)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes(m.supportedPoints)
|
||||
})
|
||||
})
|
||||
}
|
||||
if m.ticketSupported {
|
||||
// RFC 5077, Section 3.2
|
||||
b.AddUint16(extensionSessionTicket)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes(m.sessionTicket)
|
||||
})
|
||||
}
|
||||
if len(m.supportedSignatureAlgorithms) > 0 {
|
||||
// RFC 5246, Section 7.4.1.4.1
|
||||
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 {
|
||||
// RFC 8446, Section 4.2.3
|
||||
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 m.secureRenegotiationSupported {
|
||||
// RFC 5746, Section 3.2
|
||||
b.AddUint16(extensionRenegotiationInfo)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes(m.secureRenegotiation)
|
||||
})
|
||||
})
|
||||
}
|
||||
if len(m.alpnProtocols) > 0 {
|
||||
// RFC 7301, Section 3.1
|
||||
b.AddUint16(extensionALPN)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
for _, proto := range m.alpnProtocols {
|
||||
b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes([]byte(proto))
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
if m.scts {
|
||||
// RFC 6962, Section 3.3.1
|
||||
b.AddUint16(extensionSCT)
|
||||
b.AddUint16(0) // empty extension_data
|
||||
}
|
||||
if len(m.supportedVersions) > 0 {
|
||||
// RFC 8446, Section 4.2.1
|
||||
b.AddUint16(extensionSupportedVersions)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
for _, vers := range m.supportedVersions {
|
||||
b.AddUint16(vers)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
if len(m.cookie) > 0 {
|
||||
// RFC 8446, Section 4.2.2
|
||||
b.AddUint16(extensionCookie)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes(m.cookie)
|
||||
})
|
||||
})
|
||||
}
|
||||
if len(m.keyShares) > 0 {
|
||||
// RFC 8446, Section 4.2.8
|
||||
b.AddUint16(extensionKeyShare)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
for _, ks := range m.keyShares {
|
||||
b.AddUint16(uint16(ks.group))
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes(ks.data)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
if m.earlyData {
|
||||
// RFC 8446, Section 4.2.10
|
||||
b.AddUint16(extensionEarlyData)
|
||||
b.AddUint16(0) // empty extension_data
|
||||
}
|
||||
if len(m.pskModes) > 0 {
|
||||
// RFC 8446, Section 4.2.9
|
||||
b.AddUint16(extensionPSKModes)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes(m.pskModes)
|
||||
})
|
||||
})
|
||||
}
|
||||
if len(m.pskIdentities) > 0 { // pre_shared_key must be the last extension
|
||||
// RFC 8446, Section 4.2.11
|
||||
b.AddUint16(extensionPreSharedKey)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
for _, psk := range m.pskIdentities {
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes(psk.label)
|
||||
})
|
||||
b.AddUint32(psk.obfuscatedTicketAge)
|
||||
}
|
||||
})
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
for _, binder := range m.pskBinders {
|
||||
b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes(binder)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
extensionsPresent = len(b.BytesOrPanic()) > 2
|
||||
})
|
||||
|
||||
if !extensionsPresent {
|
||||
*b = bWithoutExtensions
|
||||
if len(extBytes) > 0 {
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes(extBytes)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
m.raw = b.BytesOrPanic()
|
||||
return m.raw
|
||||
m.raw, err = b.Bytes()
|
||||
return m.raw, err
|
||||
}
|
||||
|
||||
// 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 (m *clientHelloMsg) marshalWithoutBinders() []byte {
|
||||
func (m *clientHelloMsg) marshalWithoutBinders() ([]byte, error) {
|
||||
bindersLen := 2 // uint16 length prefix
|
||||
for _, binder := range m.pskBinders {
|
||||
bindersLen += 1 // uint8 length prefix
|
||||
bindersLen += len(binder)
|
||||
}
|
||||
|
||||
fullMessage := m.marshal()
|
||||
return fullMessage[:len(fullMessage)-bindersLen]
|
||||
fullMessage, err := m.marshal()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fullMessage[:len(fullMessage)-bindersLen], nil
|
||||
}
|
||||
|
||||
// updateBinders updates the m.pskBinders field, if necessary updating the
|
||||
// cached marshaled representation. The supplied binders must have the same
|
||||
// length as the current m.pskBinders.
|
||||
func (m *clientHelloMsg) updateBinders(pskBinders [][]byte) {
|
||||
func (m *clientHelloMsg) updateBinders(pskBinders [][]byte) error {
|
||||
if len(pskBinders) != len(m.pskBinders) {
|
||||
panic("tls: internal error: pskBinders length mismatch")
|
||||
return errors.New("tls: internal error: pskBinders length mismatch")
|
||||
}
|
||||
for i := range m.pskBinders {
|
||||
if len(pskBinders[i]) != len(m.pskBinders[i]) {
|
||||
panic("tls: internal error: pskBinders length mismatch")
|
||||
return errors.New("tls: internal error: pskBinders length mismatch")
|
||||
}
|
||||
}
|
||||
m.pskBinders = pskBinders
|
||||
if m.raw != nil {
|
||||
lenWithoutBinders := len(m.marshalWithoutBinders())
|
||||
helloBytes, err := m.marshalWithoutBinders()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
lenWithoutBinders := len(helloBytes)
|
||||
b := cryptobyte.NewFixedBuilder(m.raw[:lenWithoutBinders])
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
for _, binder := range m.pskBinders {
|
||||
|
@ -338,9 +345,11 @@ func (m *clientHelloMsg) updateBinders(pskBinders [][]byte) {
|
|||
}
|
||||
})
|
||||
if out, err := b.Bytes(); err != nil || len(out) != len(m.raw) {
|
||||
panic("tls: internal error: failed to update binders")
|
||||
return errors.New("tls: internal error: failed to update binders")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *clientHelloMsg) unmarshal(data []byte) bool {
|
||||
|
@ -618,9 +627,98 @@ type serverHelloMsg struct {
|
|||
selectedGroup CurveID
|
||||
}
|
||||
|
||||
func (m *serverHelloMsg) marshal() []byte {
|
||||
func (m *serverHelloMsg) marshal() ([]byte, error) {
|
||||
if m.raw != nil {
|
||||
return m.raw
|
||||
return m.raw, nil
|
||||
}
|
||||
|
||||
var exts cryptobyte.Builder
|
||||
if m.ocspStapling {
|
||||
exts.AddUint16(extensionStatusRequest)
|
||||
exts.AddUint16(0) // empty extension_data
|
||||
}
|
||||
if m.ticketSupported {
|
||||
exts.AddUint16(extensionSessionTicket)
|
||||
exts.AddUint16(0) // empty extension_data
|
||||
}
|
||||
if m.secureRenegotiationSupported {
|
||||
exts.AddUint16(extensionRenegotiationInfo)
|
||||
exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
|
||||
exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) {
|
||||
exts.AddBytes(m.secureRenegotiation)
|
||||
})
|
||||
})
|
||||
}
|
||||
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)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
extBytes, err := exts.Bytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var b cryptobyte.Builder
|
||||
|
@ -634,104 +732,15 @@ func (m *serverHelloMsg) marshal() []byte {
|
|||
b.AddUint16(m.cipherSuite)
|
||||
b.AddUint8(m.compressionMethod)
|
||||
|
||||
// If extensions aren't present, omit them.
|
||||
var extensionsPresent bool
|
||||
bWithoutExtensions := *b
|
||||
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
if m.ocspStapling {
|
||||
b.AddUint16(extensionStatusRequest)
|
||||
b.AddUint16(0) // empty extension_data
|
||||
}
|
||||
if m.ticketSupported {
|
||||
b.AddUint16(extensionSessionTicket)
|
||||
b.AddUint16(0) // empty extension_data
|
||||
}
|
||||
if m.secureRenegotiationSupported {
|
||||
b.AddUint16(extensionRenegotiationInfo)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes(m.secureRenegotiation)
|
||||
})
|
||||
})
|
||||
}
|
||||
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 len(m.scts) > 0 {
|
||||
b.AddUint16(extensionSCT)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
for _, sct := range m.scts {
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes(sct)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
if m.supportedVersion != 0 {
|
||||
b.AddUint16(extensionSupportedVersions)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint16(m.supportedVersion)
|
||||
})
|
||||
}
|
||||
if m.serverShare.group != 0 {
|
||||
b.AddUint16(extensionKeyShare)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint16(uint16(m.serverShare.group))
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes(m.serverShare.data)
|
||||
})
|
||||
})
|
||||
}
|
||||
if m.selectedIdentityPresent {
|
||||
b.AddUint16(extensionPreSharedKey)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint16(m.selectedIdentity)
|
||||
})
|
||||
}
|
||||
|
||||
if len(m.cookie) > 0 {
|
||||
b.AddUint16(extensionCookie)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes(m.cookie)
|
||||
})
|
||||
})
|
||||
}
|
||||
if m.selectedGroup != 0 {
|
||||
b.AddUint16(extensionKeyShare)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint16(uint16(m.selectedGroup))
|
||||
})
|
||||
}
|
||||
if len(m.supportedPoints) > 0 {
|
||||
b.AddUint16(extensionSupportedPoints)
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes(m.supportedPoints)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
extensionsPresent = len(b.BytesOrPanic()) > 2
|
||||
})
|
||||
|
||||
if !extensionsPresent {
|
||||
*b = bWithoutExtensions
|
||||
if len(extBytes) > 0 {
|
||||
b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||
b.AddBytes(extBytes)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
m.raw = b.BytesOrPanic()
|
||||
return m.raw
|
||||
m.raw, err = b.Bytes()
|
||||
return m.raw, err
|
||||
}
|
||||
|
||||
func (m *serverHelloMsg) unmarshal(data []byte) bool {
|
||||
|
@ -855,9 +864,9 @@ type encryptedExtensionsMsg struct {
|
|||
alpnProtocol string
|
||||
}
|
||||
|
||||
func (m *encryptedExtensionsMsg) marshal() []byte {
|
||||
func (m *encryptedExtensionsMsg) marshal() ([]byte, error) {
|
||||
if m.raw != nil {
|
||||
return m.raw
|
||||
return m.raw, nil
|
||||
}
|
||||
|
||||
var b cryptobyte.Builder
|
||||
|
@ -877,8 +886,9 @@ func (m *encryptedExtensionsMsg) marshal() []byte {
|
|||
})
|
||||
})
|
||||
|
||||
m.raw = b.BytesOrPanic()
|
||||
return m.raw
|
||||
var err error
|
||||
m.raw, err = b.Bytes()
|
||||
return m.raw, err
|
||||
}
|
||||
|
||||
func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool {
|
||||
|
@ -926,10 +936,10 @@ func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool {
|
|||
|
||||
type endOfEarlyDataMsg struct{}
|
||||
|
||||
func (m *endOfEarlyDataMsg) marshal() []byte {
|
||||
func (m *endOfEarlyDataMsg) marshal() ([]byte, error) {
|
||||
x := make([]byte, 4)
|
||||
x[0] = typeEndOfEarlyData
|
||||
return x
|
||||
return x, nil
|
||||
}
|
||||
|
||||
func (m *endOfEarlyDataMsg) unmarshal(data []byte) bool {
|
||||
|
@ -941,9 +951,9 @@ type keyUpdateMsg struct {
|
|||
updateRequested bool
|
||||
}
|
||||
|
||||
func (m *keyUpdateMsg) marshal() []byte {
|
||||
func (m *keyUpdateMsg) marshal() ([]byte, error) {
|
||||
if m.raw != nil {
|
||||
return m.raw
|
||||
return m.raw, nil
|
||||
}
|
||||
|
||||
var b cryptobyte.Builder
|
||||
|
@ -956,8 +966,9 @@ func (m *keyUpdateMsg) marshal() []byte {
|
|||
}
|
||||
})
|
||||
|
||||
m.raw = b.BytesOrPanic()
|
||||
return m.raw
|
||||
var err error
|
||||
m.raw, err = b.Bytes()
|
||||
return m.raw, err
|
||||
}
|
||||
|
||||
func (m *keyUpdateMsg) unmarshal(data []byte) bool {
|
||||
|
@ -989,9 +1000,9 @@ type newSessionTicketMsgTLS13 struct {
|
|||
maxEarlyData uint32
|
||||
}
|
||||
|
||||
func (m *newSessionTicketMsgTLS13) marshal() []byte {
|
||||
func (m *newSessionTicketMsgTLS13) marshal() ([]byte, error) {
|
||||
if m.raw != nil {
|
||||
return m.raw
|
||||
return m.raw, nil
|
||||
}
|
||||
|
||||
var b cryptobyte.Builder
|
||||
|
@ -1016,8 +1027,9 @@ func (m *newSessionTicketMsgTLS13) marshal() []byte {
|
|||
})
|
||||
})
|
||||
|
||||
m.raw = b.BytesOrPanic()
|
||||
return m.raw
|
||||
var err error
|
||||
m.raw, err = b.Bytes()
|
||||
return m.raw, err
|
||||
}
|
||||
|
||||
func (m *newSessionTicketMsgTLS13) unmarshal(data []byte) bool {
|
||||
|
@ -1070,9 +1082,9 @@ type certificateRequestMsgTLS13 struct {
|
|||
certificateAuthorities [][]byte
|
||||
}
|
||||
|
||||
func (m *certificateRequestMsgTLS13) marshal() []byte {
|
||||
func (m *certificateRequestMsgTLS13) marshal() ([]byte, error) {
|
||||
if m.raw != nil {
|
||||
return m.raw
|
||||
return m.raw, nil
|
||||
}
|
||||
|
||||
var b cryptobyte.Builder
|
||||
|
@ -1131,8 +1143,9 @@ func (m *certificateRequestMsgTLS13) marshal() []byte {
|
|||
})
|
||||
})
|
||||
|
||||
m.raw = b.BytesOrPanic()
|
||||
return m.raw
|
||||
var err error
|
||||
m.raw, err = b.Bytes()
|
||||
return m.raw, err
|
||||
}
|
||||
|
||||
func (m *certificateRequestMsgTLS13) unmarshal(data []byte) bool {
|
||||
|
@ -1216,9 +1229,9 @@ type certificateMsg struct {
|
|||
certificates [][]byte
|
||||
}
|
||||
|
||||
func (m *certificateMsg) marshal() (x []byte) {
|
||||
func (m *certificateMsg) marshal() ([]byte, error) {
|
||||
if m.raw != nil {
|
||||
return m.raw
|
||||
return m.raw, nil
|
||||
}
|
||||
|
||||
var i int
|
||||
|
@ -1227,7 +1240,7 @@ func (m *certificateMsg) marshal() (x []byte) {
|
|||
}
|
||||
|
||||
length := 3 + 3*len(m.certificates) + i
|
||||
x = make([]byte, 4+length)
|
||||
x := make([]byte, 4+length)
|
||||
x[0] = typeCertificate
|
||||
x[1] = uint8(length >> 16)
|
||||
x[2] = uint8(length >> 8)
|
||||
|
@ -1248,7 +1261,7 @@ func (m *certificateMsg) marshal() (x []byte) {
|
|||
}
|
||||
|
||||
m.raw = x
|
||||
return
|
||||
return m.raw, nil
|
||||
}
|
||||
|
||||
func (m *certificateMsg) unmarshal(data []byte) bool {
|
||||
|
@ -1295,9 +1308,9 @@ type certificateMsgTLS13 struct {
|
|||
scts bool
|
||||
}
|
||||
|
||||
func (m *certificateMsgTLS13) marshal() []byte {
|
||||
func (m *certificateMsgTLS13) marshal() ([]byte, error) {
|
||||
if m.raw != nil {
|
||||
return m.raw
|
||||
return m.raw, nil
|
||||
}
|
||||
|
||||
var b cryptobyte.Builder
|
||||
|
@ -1315,8 +1328,9 @@ func (m *certificateMsgTLS13) marshal() []byte {
|
|||
marshalCertificate(b, certificate)
|
||||
})
|
||||
|
||||
m.raw = b.BytesOrPanic()
|
||||
return m.raw
|
||||
var err error
|
||||
m.raw, err = b.Bytes()
|
||||
return m.raw, err
|
||||
}
|
||||
|
||||
func marshalCertificate(b *cryptobyte.Builder, certificate Certificate) {
|
||||
|
@ -1439,9 +1453,9 @@ type serverKeyExchangeMsg struct {
|
|||
key []byte
|
||||
}
|
||||
|
||||
func (m *serverKeyExchangeMsg) marshal() []byte {
|
||||
func (m *serverKeyExchangeMsg) marshal() ([]byte, error) {
|
||||
if m.raw != nil {
|
||||
return m.raw
|
||||
return m.raw, nil
|
||||
}
|
||||
length := len(m.key)
|
||||
x := make([]byte, length+4)
|
||||
|
@ -1452,7 +1466,7 @@ func (m *serverKeyExchangeMsg) marshal() []byte {
|
|||
copy(x[4:], m.key)
|
||||
|
||||
m.raw = x
|
||||
return x
|
||||
return x, nil
|
||||
}
|
||||
|
||||
func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool {
|
||||
|
@ -1469,9 +1483,9 @@ type certificateStatusMsg struct {
|
|||
response []byte
|
||||
}
|
||||
|
||||
func (m *certificateStatusMsg) marshal() []byte {
|
||||
func (m *certificateStatusMsg) marshal() ([]byte, error) {
|
||||
if m.raw != nil {
|
||||
return m.raw
|
||||
return m.raw, nil
|
||||
}
|
||||
|
||||
var b cryptobyte.Builder
|
||||
|
@ -1483,8 +1497,9 @@ func (m *certificateStatusMsg) marshal() []byte {
|
|||
})
|
||||
})
|
||||
|
||||
m.raw = b.BytesOrPanic()
|
||||
return m.raw
|
||||
var err error
|
||||
m.raw, err = b.Bytes()
|
||||
return m.raw, err
|
||||
}
|
||||
|
||||
func (m *certificateStatusMsg) unmarshal(data []byte) bool {
|
||||
|
@ -1503,10 +1518,10 @@ func (m *certificateStatusMsg) unmarshal(data []byte) bool {
|
|||
|
||||
type serverHelloDoneMsg struct{}
|
||||
|
||||
func (m *serverHelloDoneMsg) marshal() []byte {
|
||||
func (m *serverHelloDoneMsg) marshal() ([]byte, error) {
|
||||
x := make([]byte, 4)
|
||||
x[0] = typeServerHelloDone
|
||||
return x
|
||||
return x, nil
|
||||
}
|
||||
|
||||
func (m *serverHelloDoneMsg) unmarshal(data []byte) bool {
|
||||
|
@ -1518,9 +1533,9 @@ type clientKeyExchangeMsg struct {
|
|||
ciphertext []byte
|
||||
}
|
||||
|
||||
func (m *clientKeyExchangeMsg) marshal() []byte {
|
||||
func (m *clientKeyExchangeMsg) marshal() ([]byte, error) {
|
||||
if m.raw != nil {
|
||||
return m.raw
|
||||
return m.raw, nil
|
||||
}
|
||||
length := len(m.ciphertext)
|
||||
x := make([]byte, length+4)
|
||||
|
@ -1531,7 +1546,7 @@ func (m *clientKeyExchangeMsg) marshal() []byte {
|
|||
copy(x[4:], m.ciphertext)
|
||||
|
||||
m.raw = x
|
||||
return x
|
||||
return x, nil
|
||||
}
|
||||
|
||||
func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
|
||||
|
@ -1552,9 +1567,9 @@ type finishedMsg struct {
|
|||
verifyData []byte
|
||||
}
|
||||
|
||||
func (m *finishedMsg) marshal() []byte {
|
||||
func (m *finishedMsg) marshal() ([]byte, error) {
|
||||
if m.raw != nil {
|
||||
return m.raw
|
||||
return m.raw, nil
|
||||
}
|
||||
|
||||
var b cryptobyte.Builder
|
||||
|
@ -1563,8 +1578,9 @@ func (m *finishedMsg) marshal() []byte {
|
|||
b.AddBytes(m.verifyData)
|
||||
})
|
||||
|
||||
m.raw = b.BytesOrPanic()
|
||||
return m.raw
|
||||
var err error
|
||||
m.raw, err = b.Bytes()
|
||||
return m.raw, err
|
||||
}
|
||||
|
||||
func (m *finishedMsg) unmarshal(data []byte) bool {
|
||||
|
@ -1586,9 +1602,9 @@ type certificateRequestMsg struct {
|
|||
certificateAuthorities [][]byte
|
||||
}
|
||||
|
||||
func (m *certificateRequestMsg) marshal() (x []byte) {
|
||||
func (m *certificateRequestMsg) marshal() ([]byte, error) {
|
||||
if m.raw != nil {
|
||||
return m.raw
|
||||
return m.raw, nil
|
||||
}
|
||||
|
||||
// See RFC 4346, Section 7.4.4.
|
||||
|
@ -1603,7 +1619,7 @@ func (m *certificateRequestMsg) marshal() (x []byte) {
|
|||
length += 2 + 2*len(m.supportedSignatureAlgorithms)
|
||||
}
|
||||
|
||||
x = make([]byte, 4+length)
|
||||
x := make([]byte, 4+length)
|
||||
x[0] = typeCertificateRequest
|
||||
x[1] = uint8(length >> 16)
|
||||
x[2] = uint8(length >> 8)
|
||||
|
@ -1638,7 +1654,7 @@ func (m *certificateRequestMsg) marshal() (x []byte) {
|
|||
}
|
||||
|
||||
m.raw = x
|
||||
return
|
||||
return m.raw, nil
|
||||
}
|
||||
|
||||
func (m *certificateRequestMsg) unmarshal(data []byte) bool {
|
||||
|
@ -1724,9 +1740,9 @@ type certificateVerifyMsg struct {
|
|||
signature []byte
|
||||
}
|
||||
|
||||
func (m *certificateVerifyMsg) marshal() (x []byte) {
|
||||
func (m *certificateVerifyMsg) marshal() ([]byte, error) {
|
||||
if m.raw != nil {
|
||||
return m.raw
|
||||
return m.raw, nil
|
||||
}
|
||||
|
||||
var b cryptobyte.Builder
|
||||
|
@ -1740,8 +1756,9 @@ func (m *certificateVerifyMsg) marshal() (x []byte) {
|
|||
})
|
||||
})
|
||||
|
||||
m.raw = b.BytesOrPanic()
|
||||
return m.raw
|
||||
var err error
|
||||
m.raw, err = b.Bytes()
|
||||
return m.raw, err
|
||||
}
|
||||
|
||||
func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
|
||||
|
@ -1764,15 +1781,15 @@ type newSessionTicketMsg struct {
|
|||
ticket []byte
|
||||
}
|
||||
|
||||
func (m *newSessionTicketMsg) marshal() (x []byte) {
|
||||
func (m *newSessionTicketMsg) marshal() ([]byte, error) {
|
||||
if m.raw != nil {
|
||||
return m.raw
|
||||
return m.raw, nil
|
||||
}
|
||||
|
||||
// See RFC 5077, Section 3.3.
|
||||
ticketLen := len(m.ticket)
|
||||
length := 2 + 4 + ticketLen
|
||||
x = make([]byte, 4+length)
|
||||
x := make([]byte, 4+length)
|
||||
x[0] = typeNewSessionTicket
|
||||
x[1] = uint8(length >> 16)
|
||||
x[2] = uint8(length >> 8)
|
||||
|
@ -1783,7 +1800,7 @@ func (m *newSessionTicketMsg) marshal() (x []byte) {
|
|||
|
||||
m.raw = x
|
||||
|
||||
return
|
||||
return m.raw, nil
|
||||
}
|
||||
|
||||
func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
|
||||
|
@ -1811,10 +1828,25 @@ func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
|
|||
type helloRequestMsg struct {
|
||||
}
|
||||
|
||||
func (*helloRequestMsg) marshal() []byte {
|
||||
return []byte{typeHelloRequest, 0, 0, 0}
|
||||
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)
|
||||
}
|
||||
|
||||
// transcriptMsg is a helper used to marshal and hash messages which typically
|
||||
// are not written to the wire, and as such aren't hashed during Conn.writeRecord.
|
||||
func transcriptMsg(msg handshakeMessage, h transcriptHash) error {
|
||||
data, err := msg.marshal()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.Write(data)
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue