boringssl/ssl/test/runner/handshake_messages.go
Adam Langley 512a289a8a Add support for dummy PQ padding.
This extension will be used to measure the latency impact of potentially
sending a post-quantum key share by default. At this time it's purely
measuring the impact of the client sending the key share, not the server
replying with a ciphertext.

We could use the existing padding extension for this but that extension
doesn't allow the server to echo it, so we would need a different
extension in the future anyway. Thus we just create one now.

We can assume that modern clients will be using TLS 1.3 by the time that
PQ key-exchange is established and thus the key share will be sent in
all ClientHello messages. However, since TLS 1.3 isn't quite here yet,
this extension is also sent for TLS 1.0–1.2 ClientHellos. The latency
impact should be the same either way.

Change-Id: Ie4a17551f6589b28505797e8c54cddbe3338dfe5
Reviewed-on: https://boringssl-review.googlesource.com/24585
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: David Benjamin <davidben@google.com>
2018-01-10 00:27:31 +00:00

2466 lines
61 KiB
Go

// 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 runner
import (
"bytes"
"encoding/binary"
"fmt"
)
func writeLen(buf []byte, v, size int) {
for i := 0; i < size; i++ {
buf[size-i-1] = byte(v)
v >>= 8
}
if v != 0 {
panic("length is too long")
}
}
type byteBuilder struct {
buf *[]byte
start int
prefixLen int
child *byteBuilder
}
func newByteBuilder() *byteBuilder {
buf := make([]byte, 0, 32)
return &byteBuilder{buf: &buf}
}
func (bb *byteBuilder) len() int {
return len(*bb.buf) - bb.start - bb.prefixLen
}
func (bb *byteBuilder) data() []byte {
bb.flush()
return (*bb.buf)[bb.start+bb.prefixLen:]
}
func (bb *byteBuilder) flush() {
if bb.child == nil {
return
}
bb.child.flush()
writeLen((*bb.buf)[bb.child.start:], bb.child.len(), bb.child.prefixLen)
bb.child = nil
return
}
func (bb *byteBuilder) finish() []byte {
bb.flush()
return *bb.buf
}
func (bb *byteBuilder) addU8(u uint8) {
bb.flush()
*bb.buf = append(*bb.buf, u)
}
func (bb *byteBuilder) addU16(u uint16) {
bb.flush()
*bb.buf = append(*bb.buf, byte(u>>8), byte(u))
}
func (bb *byteBuilder) addU24(u int) {
bb.flush()
*bb.buf = append(*bb.buf, byte(u>>16), byte(u>>8), byte(u))
}
func (bb *byteBuilder) addU32(u uint32) {
bb.flush()
*bb.buf = append(*bb.buf, byte(u>>24), byte(u>>16), byte(u>>8), byte(u))
}
func (bb *byteBuilder) addU64(u uint64) {
bb.flush()
var b [8]byte
binary.BigEndian.PutUint64(b[:], u)
*bb.buf = append(*bb.buf, b[:]...)
}
func (bb *byteBuilder) addU8LengthPrefixed() *byteBuilder {
return bb.createChild(1)
}
func (bb *byteBuilder) addU16LengthPrefixed() *byteBuilder {
return bb.createChild(2)
}
func (bb *byteBuilder) addU24LengthPrefixed() *byteBuilder {
return bb.createChild(3)
}
func (bb *byteBuilder) addU32LengthPrefixed() *byteBuilder {
return bb.createChild(4)
}
func (bb *byteBuilder) addBytes(b []byte) {
bb.flush()
*bb.buf = append(*bb.buf, b...)
}
func (bb *byteBuilder) createChild(lengthPrefixSize int) *byteBuilder {
bb.flush()
bb.child = &byteBuilder{
buf: bb.buf,
start: len(*bb.buf),
prefixLen: lengthPrefixSize,
}
for i := 0; i < lengthPrefixSize; i++ {
*bb.buf = append(*bb.buf, 0)
}
return bb.child
}
func (bb *byteBuilder) discardChild() {
if bb.child == nil {
return
}
*bb.buf = (*bb.buf)[:bb.child.start]
bb.child = nil
}
type byteReader []byte
func (br *byteReader) readInternal(out *byteReader, n int) bool {
if len(*br) < n {
return false
}
*out = (*br)[:n]
*br = (*br)[n:]
return true
}
func (br *byteReader) readBytes(out *[]byte, n int) bool {
var child byteReader
if !br.readInternal(&child, n) {
return false
}
*out = []byte(child)
return true
}
func (br *byteReader) readUint(out *uint64, n int) bool {
var b []byte
if !br.readBytes(&b, n) {
return false
}
*out = 0
for _, v := range b {
*out <<= 8
*out |= uint64(v)
}
return true
}
func (br *byteReader) readU8(out *uint8) bool {
var b []byte
if !br.readBytes(&b, 1) {
return false
}
*out = b[0]
return true
}
func (br *byteReader) readU16(out *uint16) bool {
var v uint64
if !br.readUint(&v, 2) {
return false
}
*out = uint16(v)
return true
}
func (br *byteReader) readU24(out *uint32) bool {
var v uint64
if !br.readUint(&v, 3) {
return false
}
*out = uint32(v)
return true
}
func (br *byteReader) readU32(out *uint32) bool {
var v uint64
if !br.readUint(&v, 4) {
return false
}
*out = uint32(v)
return true
}
func (br *byteReader) readU64(out *uint64) bool {
return br.readUint(out, 8)
}
func (br *byteReader) readLengthPrefixed(out *byteReader, n int) bool {
var length uint64
return br.readUint(&length, n) &&
uint64(len(*br)) >= length &&
br.readInternal(out, int(length))
}
func (br *byteReader) readLengthPrefixedBytes(out *[]byte, n int) bool {
var length uint64
return br.readUint(&length, n) &&
uint64(len(*br)) >= length &&
br.readBytes(out, int(length))
}
func (br *byteReader) readU8LengthPrefixed(out *byteReader) bool {
return br.readLengthPrefixed(out, 1)
}
func (br *byteReader) readU8LengthPrefixedBytes(out *[]byte) bool {
return br.readLengthPrefixedBytes(out, 1)
}
func (br *byteReader) readU16LengthPrefixed(out *byteReader) bool {
return br.readLengthPrefixed(out, 2)
}
func (br *byteReader) readU16LengthPrefixedBytes(out *[]byte) bool {
return br.readLengthPrefixedBytes(out, 2)
}
func (br *byteReader) readU24LengthPrefixed(out *byteReader) bool {
return br.readLengthPrefixed(out, 3)
}
func (br *byteReader) readU24LengthPrefixedBytes(out *[]byte) bool {
return br.readLengthPrefixedBytes(out, 3)
}
func (br *byteReader) readU32LengthPrefixed(out *byteReader) bool {
return br.readLengthPrefixed(out, 4)
}
func (br *byteReader) readU32LengthPrefixedBytes(out *[]byte) bool {
return br.readLengthPrefixedBytes(out, 4)
}
type keyShareEntry struct {
group CurveID
keyExchange []byte
}
type pskIdentity struct {
ticket []uint8
obfuscatedTicketAge uint32
}
type clientHelloMsg struct {
raw []byte
isDTLS bool
vers uint16
random []byte
sessionId []byte
cookie []byte
cipherSuites []uint16
compressionMethods []uint8
nextProtoNeg bool
serverName string
ocspStapling bool
supportedCurves []CurveID
supportedPoints []uint8
hasKeyShares bool
keyShareExtension uint16
keyShares []keyShareEntry
trailingKeyShareData bool
pskIdentities []pskIdentity
pskKEModes []byte
pskBinders [][]uint8
hasEarlyData bool
tls13Cookie []byte
ticketSupported bool
sessionTicket []uint8
signatureAlgorithms []signatureAlgorithm
supportedVersions []uint16
secureRenegotiation []byte
alpnProtocols []string
duplicateExtension bool
channelIDSupported bool
npnAfterAlpn bool
extendedMasterSecret bool
srtpProtectionProfiles []uint16
srtpMasterKeyIdentifier string
sctListSupported bool
customExtension string
hasGREASEExtension bool
pskBinderFirst bool
omitExtensions bool
emptyExtensions bool
pad int
dummyPQPaddingLen int
}
func (m *clientHelloMsg) equal(i interface{}) bool {
m1, ok := i.(*clientHelloMsg)
if !ok {
return false
}
return bytes.Equal(m.raw, m1.raw) &&
m.isDTLS == m1.isDTLS &&
m.vers == m1.vers &&
bytes.Equal(m.random, m1.random) &&
bytes.Equal(m.sessionId, m1.sessionId) &&
bytes.Equal(m.cookie, m1.cookie) &&
eqUint16s(m.cipherSuites, m1.cipherSuites) &&
bytes.Equal(m.compressionMethods, m1.compressionMethods) &&
m.nextProtoNeg == m1.nextProtoNeg &&
m.serverName == m1.serverName &&
m.ocspStapling == m1.ocspStapling &&
eqCurveIDs(m.supportedCurves, m1.supportedCurves) &&
bytes.Equal(m.supportedPoints, m1.supportedPoints) &&
m.hasKeyShares == m1.hasKeyShares &&
eqKeyShareEntryLists(m.keyShares, m1.keyShares) &&
m.trailingKeyShareData == m1.trailingKeyShareData &&
eqPSKIdentityLists(m.pskIdentities, m1.pskIdentities) &&
bytes.Equal(m.pskKEModes, m1.pskKEModes) &&
eqByteSlices(m.pskBinders, m1.pskBinders) &&
m.hasEarlyData == m1.hasEarlyData &&
bytes.Equal(m.tls13Cookie, m1.tls13Cookie) &&
m.ticketSupported == m1.ticketSupported &&
bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
eqSignatureAlgorithms(m.signatureAlgorithms, m1.signatureAlgorithms) &&
eqUint16s(m.supportedVersions, m1.supportedVersions) &&
bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
(m.secureRenegotiation == nil) == (m1.secureRenegotiation == nil) &&
eqStrings(m.alpnProtocols, m1.alpnProtocols) &&
m.duplicateExtension == m1.duplicateExtension &&
m.channelIDSupported == m1.channelIDSupported &&
m.npnAfterAlpn == m1.npnAfterAlpn &&
m.extendedMasterSecret == m1.extendedMasterSecret &&
eqUint16s(m.srtpProtectionProfiles, m1.srtpProtectionProfiles) &&
m.srtpMasterKeyIdentifier == m1.srtpMasterKeyIdentifier &&
m.sctListSupported == m1.sctListSupported &&
m.customExtension == m1.customExtension &&
m.hasGREASEExtension == m1.hasGREASEExtension &&
m.pskBinderFirst == m1.pskBinderFirst &&
m.omitExtensions == m1.omitExtensions &&
m.emptyExtensions == m1.emptyExtensions &&
m.pad == m1.pad &&
m.dummyPQPaddingLen == m1.dummyPQPaddingLen
}
func (m *clientHelloMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
handshakeMsg := newByteBuilder()
handshakeMsg.addU8(typeClientHello)
hello := handshakeMsg.addU24LengthPrefixed()
hello.addU16(m.vers)
hello.addBytes(m.random)
sessionId := hello.addU8LengthPrefixed()
sessionId.addBytes(m.sessionId)
if m.isDTLS {
cookie := hello.addU8LengthPrefixed()
cookie.addBytes(m.cookie)
}
cipherSuites := hello.addU16LengthPrefixed()
for _, suite := range m.cipherSuites {
cipherSuites.addU16(suite)
}
compressionMethods := hello.addU8LengthPrefixed()
compressionMethods.addBytes(m.compressionMethods)
extensions := hello.addU16LengthPrefixed()
if len(m.pskIdentities) > 0 && m.pskBinderFirst {
extensions.addU16(extensionPreSharedKey)
pskExtension := extensions.addU16LengthPrefixed()
pskIdentities := pskExtension.addU16LengthPrefixed()
for _, psk := range m.pskIdentities {
pskIdentities.addU16LengthPrefixed().addBytes(psk.ticket)
pskIdentities.addU32(psk.obfuscatedTicketAge)
}
pskBinders := pskExtension.addU16LengthPrefixed()
for _, binder := range m.pskBinders {
pskBinders.addU8LengthPrefixed().addBytes(binder)
}
}
if m.duplicateExtension {
// Add a duplicate bogus extension at the beginning and end.
extensions.addU16(0xffff)
extensions.addU16(0) // 0-length for empty extension
}
if m.nextProtoNeg && !m.npnAfterAlpn {
extensions.addU16(extensionNextProtoNeg)
extensions.addU16(0) // The length is always 0
}
if len(m.serverName) > 0 {
extensions.addU16(extensionServerName)
serverNameList := extensions.addU16LengthPrefixed()
// RFC 3546, section 3.1
//
// struct {
// NameType name_type;
// select (name_type) {
// case host_name: HostName;
// } name;
// } ServerName;
//
// enum {
// host_name(0), (255)
// } NameType;
//
// opaque HostName<1..2^16-1>;
//
// struct {
// ServerName server_name_list<1..2^16-1>
// } ServerNameList;
serverName := serverNameList.addU16LengthPrefixed()
serverName.addU8(0) // NameType host_name(0)
hostName := serverName.addU16LengthPrefixed()
hostName.addBytes([]byte(m.serverName))
}
if m.ocspStapling {
extensions.addU16(extensionStatusRequest)
certificateStatusRequest := extensions.addU16LengthPrefixed()
// RFC 4366, section 3.6
certificateStatusRequest.addU8(1) // OCSP type
// Two zero valued uint16s for the two lengths.
certificateStatusRequest.addU16(0) // ResponderID length
certificateStatusRequest.addU16(0) // Extensions length
}
if len(m.supportedCurves) > 0 {
// http://tools.ietf.org/html/rfc4492#section-5.1.1
extensions.addU16(extensionSupportedCurves)
supportedCurvesList := extensions.addU16LengthPrefixed()
supportedCurves := supportedCurvesList.addU16LengthPrefixed()
for _, curve := range m.supportedCurves {
supportedCurves.addU16(uint16(curve))
}
}
if len(m.supportedPoints) > 0 {
// http://tools.ietf.org/html/rfc4492#section-5.1.2
extensions.addU16(extensionSupportedPoints)
supportedPointsList := extensions.addU16LengthPrefixed()
supportedPoints := supportedPointsList.addU8LengthPrefixed()
supportedPoints.addBytes(m.supportedPoints)
}
if m.hasKeyShares {
extensions.addU16(m.keyShareExtension)
keyShareList := extensions.addU16LengthPrefixed()
keyShares := keyShareList.addU16LengthPrefixed()
for _, keyShare := range m.keyShares {
keyShares.addU16(uint16(keyShare.group))
keyExchange := keyShares.addU16LengthPrefixed()
keyExchange.addBytes(keyShare.keyExchange)
}
if m.trailingKeyShareData {
keyShares.addU8(0)
}
}
if len(m.pskKEModes) > 0 {
extensions.addU16(extensionPSKKeyExchangeModes)
pskModesExtension := extensions.addU16LengthPrefixed()
pskModesExtension.addU8LengthPrefixed().addBytes(m.pskKEModes)
}
if m.hasEarlyData {
extensions.addU16(extensionEarlyData)
extensions.addU16(0) // The length is zero.
}
if len(m.tls13Cookie) > 0 {
extensions.addU16(extensionCookie)
body := extensions.addU16LengthPrefixed()
body.addU16LengthPrefixed().addBytes(m.tls13Cookie)
}
if m.ticketSupported {
// http://tools.ietf.org/html/rfc5077#section-3.2
extensions.addU16(extensionSessionTicket)
sessionTicketExtension := extensions.addU16LengthPrefixed()
sessionTicketExtension.addBytes(m.sessionTicket)
}
if len(m.signatureAlgorithms) > 0 {
// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
extensions.addU16(extensionSignatureAlgorithms)
signatureAlgorithmsExtension := extensions.addU16LengthPrefixed()
signatureAlgorithms := signatureAlgorithmsExtension.addU16LengthPrefixed()
for _, sigAlg := range m.signatureAlgorithms {
signatureAlgorithms.addU16(uint16(sigAlg))
}
}
if len(m.supportedVersions) > 0 {
extensions.addU16(extensionSupportedVersions)
supportedVersionsExtension := extensions.addU16LengthPrefixed()
supportedVersions := supportedVersionsExtension.addU8LengthPrefixed()
for _, version := range m.supportedVersions {
supportedVersions.addU16(uint16(version))
}
}
if m.secureRenegotiation != nil {
extensions.addU16(extensionRenegotiationInfo)
secureRenegoExt := extensions.addU16LengthPrefixed()
secureRenego := secureRenegoExt.addU8LengthPrefixed()
secureRenego.addBytes(m.secureRenegotiation)
}
if len(m.alpnProtocols) > 0 {
// https://tools.ietf.org/html/rfc7301#section-3.1
extensions.addU16(extensionALPN)
alpnExtension := extensions.addU16LengthPrefixed()
protocolNameList := alpnExtension.addU16LengthPrefixed()
for _, s := range m.alpnProtocols {
protocolName := protocolNameList.addU8LengthPrefixed()
protocolName.addBytes([]byte(s))
}
}
if m.channelIDSupported {
extensions.addU16(extensionChannelID)
extensions.addU16(0) // Length is always 0
}
if m.nextProtoNeg && m.npnAfterAlpn {
extensions.addU16(extensionNextProtoNeg)
extensions.addU16(0) // Length is always 0
}
if m.duplicateExtension {
// Add a duplicate bogus extension at the beginning and end.
extensions.addU16(0xffff)
extensions.addU16(0)
}
if m.extendedMasterSecret {
// https://tools.ietf.org/html/rfc7627
extensions.addU16(extensionExtendedMasterSecret)
extensions.addU16(0) // Length is always 0
}
if len(m.srtpProtectionProfiles) > 0 {
// https://tools.ietf.org/html/rfc5764#section-4.1.1
extensions.addU16(extensionUseSRTP)
useSrtpExt := extensions.addU16LengthPrefixed()
srtpProtectionProfiles := useSrtpExt.addU16LengthPrefixed()
for _, p := range m.srtpProtectionProfiles {
srtpProtectionProfiles.addU16(p)
}
srtpMki := useSrtpExt.addU8LengthPrefixed()
srtpMki.addBytes([]byte(m.srtpMasterKeyIdentifier))
}
if m.sctListSupported {
extensions.addU16(extensionSignedCertificateTimestamp)
extensions.addU16(0) // Length is always 0
}
if l := len(m.customExtension); l > 0 {
extensions.addU16(extensionCustom)
customExt := extensions.addU16LengthPrefixed()
customExt.addBytes([]byte(m.customExtension))
}
// The PSK extension must be last (draft-ietf-tls-tls13-18 section 4.2.6).
if len(m.pskIdentities) > 0 && !m.pskBinderFirst {
extensions.addU16(extensionPreSharedKey)
pskExtension := extensions.addU16LengthPrefixed()
pskIdentities := pskExtension.addU16LengthPrefixed()
for _, psk := range m.pskIdentities {
pskIdentities.addU16LengthPrefixed().addBytes(psk.ticket)
pskIdentities.addU32(psk.obfuscatedTicketAge)
}
pskBinders := pskExtension.addU16LengthPrefixed()
for _, binder := range m.pskBinders {
pskBinders.addU8LengthPrefixed().addBytes(binder)
}
}
if m.pad != 0 && hello.len()%m.pad != 0 {
extensions.addU16(extensionPadding)
padding := extensions.addU16LengthPrefixed()
// Note hello.len() has changed at this point from the length
// prefix.
if l := hello.len() % m.pad; l != 0 {
padding.addBytes(make([]byte, m.pad-l))
}
}
if m.omitExtensions || m.emptyExtensions {
// Silently erase any extensions which were sent.
hello.discardChild()
if m.emptyExtensions {
hello.addU16(0)
}
}
m.raw = handshakeMsg.finish()
// Sanity-check padding.
if m.pad != 0 && (len(m.raw)-4)%m.pad != 0 {
panic(fmt.Sprintf("%d is not a multiple of %d", len(m.raw)-4, m.pad))
}
return m.raw
}
func parseSignatureAlgorithms(reader *byteReader, out *[]signatureAlgorithm) bool {
var sigAlgs byteReader
if !reader.readU16LengthPrefixed(&sigAlgs) {
return false
}
*out = make([]signatureAlgorithm, 0, len(sigAlgs)/2)
for len(sigAlgs) > 0 {
var v uint16
if !sigAlgs.readU16(&v) {
return false
}
*out = append(*out, signatureAlgorithm(v))
}
return true
}
func (m *clientHelloMsg) unmarshal(data []byte) bool {
m.raw = data
reader := byteReader(data[4:])
if !reader.readU16(&m.vers) ||
!reader.readBytes(&m.random, 32) ||
!reader.readU8LengthPrefixedBytes(&m.sessionId) ||
len(m.sessionId) > 32 {
return false
}
if m.isDTLS {
if !reader.readU8LengthPrefixedBytes(&m.cookie) ||
len(m.cookie) > 32 {
return false
}
}
var cipherSuites byteReader
if !reader.readU16LengthPrefixed(&cipherSuites) ||
!reader.readU8LengthPrefixedBytes(&m.compressionMethods) {
return false
}
m.cipherSuites = make([]uint16, 0, len(cipherSuites)/2)
for len(cipherSuites) > 0 {
var v uint16
if !cipherSuites.readU16(&v) {
return false
}
m.cipherSuites = append(m.cipherSuites, v)
if v == scsvRenegotiation {
m.secureRenegotiation = []byte{}
}
}
m.nextProtoNeg = false
m.serverName = ""
m.ocspStapling = false
m.keyShares = nil
m.pskIdentities = nil
m.hasEarlyData = false
m.ticketSupported = false
m.sessionTicket = nil
m.signatureAlgorithms = nil
m.supportedVersions = nil
m.alpnProtocols = nil
m.extendedMasterSecret = false
m.customExtension = ""
if len(reader) == 0 {
// ClientHello is optionally followed by extension data
return true
}
var extensions byteReader
if !reader.readU16LengthPrefixed(&extensions) || len(reader) != 0 {
return false
}
for len(extensions) > 0 {
var extension uint16
var body byteReader
if !extensions.readU16(&extension) ||
!extensions.readU16LengthPrefixed(&body) {
return false
}
switch extension {
case extensionServerName:
var names byteReader
if !body.readU16LengthPrefixed(&names) || len(body) != 0 {
return false
}
for len(names) > 0 {
var nameType byte
var name []byte
if !names.readU8(&nameType) ||
!names.readU16LengthPrefixedBytes(&name) {
return false
}
if nameType == 0 {
m.serverName = string(name)
}
}
case extensionNextProtoNeg:
if len(body) != 0 {
return false
}
m.nextProtoNeg = true
case extensionStatusRequest:
m.ocspStapling = len(body) > 0 && body[0] == statusTypeOCSP
case extensionSupportedCurves:
// http://tools.ietf.org/html/rfc4492#section-5.5.1
var curves byteReader
if !body.readU16LengthPrefixed(&curves) || len(body) != 0 {
return false
}
m.supportedCurves = make([]CurveID, 0, len(curves)/2)
for len(curves) > 0 {
var v uint16
if !curves.readU16(&v) {
return false
}
m.supportedCurves = append(m.supportedCurves, CurveID(v))
}
case extensionSupportedPoints:
// http://tools.ietf.org/html/rfc4492#section-5.5.2
if !body.readU8LengthPrefixedBytes(&m.supportedPoints) || len(body) != 0 {
return false
}
case extensionSessionTicket:
// http://tools.ietf.org/html/rfc5077#section-3.2
m.ticketSupported = true
m.sessionTicket = []byte(body)
case extensionOldKeyShare, extensionNewKeyShare:
// We assume the client only supports one of draft-22 or draft-23.
if m.keyShareExtension != 0 {
return false
}
m.keyShareExtension = extension
// draft-ietf-tls-tls13 section 6.3.2.3
var keyShares byteReader
if !body.readU16LengthPrefixed(&keyShares) || len(body) != 0 {
return false
}
m.hasKeyShares = true
for len(keyShares) > 0 {
var entry keyShareEntry
var group uint16
if !keyShares.readU16(&group) ||
!keyShares.readU16LengthPrefixedBytes(&entry.keyExchange) {
return false
}
entry.group = CurveID(group)
m.keyShares = append(m.keyShares, entry)
}
case extensionPreSharedKey:
// draft-ietf-tls-tls13-18 section 4.2.6
var psks, binders byteReader
if !body.readU16LengthPrefixed(&psks) ||
!body.readU16LengthPrefixed(&binders) ||
len(body) != 0 {
return false
}
for len(psks) > 0 {
var psk pskIdentity
if !psks.readU16LengthPrefixedBytes(&psk.ticket) ||
!psks.readU32(&psk.obfuscatedTicketAge) {
return false
}
m.pskIdentities = append(m.pskIdentities, psk)
}
for len(binders) > 0 {
var binder []byte
if !binders.readU8LengthPrefixedBytes(&binder) {
return false
}
m.pskBinders = append(m.pskBinders, binder)
}
// There must be the same number of identities as binders.
if len(m.pskIdentities) != len(m.pskBinders) {
return false
}
case extensionPSKKeyExchangeModes:
// draft-ietf-tls-tls13-18 section 4.2.7
if !body.readU8LengthPrefixedBytes(&m.pskKEModes) || len(body) != 0 {
return false
}
case extensionEarlyData:
// draft-ietf-tls-tls13 section 6.3.2.5
if len(body) != 0 {
return false
}
m.hasEarlyData = true
case extensionCookie:
if !body.readU16LengthPrefixedBytes(&m.tls13Cookie) || len(body) != 0 {
return false
}
case extensionSignatureAlgorithms:
// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
if !parseSignatureAlgorithms(&body, &m.signatureAlgorithms) || len(body) != 0 {
return false
}
case extensionSupportedVersions:
var versions byteReader
if !body.readU8LengthPrefixed(&versions) || len(body) != 0 {
return false
}
m.supportedVersions = make([]uint16, 0, len(versions)/2)
for len(versions) > 0 {
var v uint16
if !versions.readU16(&v) {
return false
}
m.supportedVersions = append(m.supportedVersions, v)
}
case extensionRenegotiationInfo:
if !body.readU8LengthPrefixedBytes(&m.secureRenegotiation) || len(body) != 0 {
return false
}
case extensionALPN:
var protocols byteReader
if !body.readU16LengthPrefixed(&protocols) || len(body) != 0 {
return false
}
for len(protocols) > 0 {
var protocol []byte
if !protocols.readU8LengthPrefixedBytes(&protocol) {
return false
}
m.alpnProtocols = append(m.alpnProtocols, string(protocol))
}
case extensionChannelID:
if len(body) != 0 {
return false
}
m.channelIDSupported = true
case extensionExtendedMasterSecret:
if len(body) != 0 {
return false
}
m.extendedMasterSecret = true
case extensionUseSRTP:
var profiles byteReader
var mki []byte
if !body.readU16LengthPrefixed(&profiles) ||
!body.readU8LengthPrefixedBytes(&mki) ||
len(body) != 0 {
return false
}
m.srtpProtectionProfiles = make([]uint16, 0, len(profiles)/2)
for len(profiles) > 0 {
var v uint16
if !profiles.readU16(&v) {
return false
}
m.srtpProtectionProfiles = append(m.srtpProtectionProfiles, v)
}
m.srtpMasterKeyIdentifier = string(mki)
case extensionSignedCertificateTimestamp:
if len(body) != 0 {
return false
}
m.sctListSupported = true
case extensionCustom:
m.customExtension = string(body)
case extensionDummyPQPadding:
if len(body) == 0 {
return false
}
m.dummyPQPaddingLen = len(body)
}
if isGREASEValue(extension) {
m.hasGREASEExtension = true
}
}
return true
}
type serverHelloMsg struct {
raw []byte
isDTLS bool
vers uint16
versOverride uint16
supportedVersOverride uint16
random []byte
sessionId []byte
cipherSuite uint16
hasKeyShare bool
keyShare keyShareEntry
hasPSKIdentity bool
pskIdentity uint16
compressionMethod uint8
customExtension string
unencryptedALPN string
omitExtensions bool
emptyExtensions bool
extensions serverExtensions
}
func (m *serverHelloMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
handshakeMsg := newByteBuilder()
handshakeMsg.addU8(typeServerHello)
hello := handshakeMsg.addU24LengthPrefixed()
// m.vers is used both to determine the format of the rest of the
// ServerHello and to override the value, so include a second version
// field.
vers, ok := wireToVersion(m.vers, m.isDTLS)
if !ok {
panic("unknown version")
}
if m.versOverride != 0 {
hello.addU16(m.versOverride)
} else if vers >= VersionTLS13 {
hello.addU16(VersionTLS12)
} else {
hello.addU16(m.vers)
}
hello.addBytes(m.random)
sessionId := hello.addU8LengthPrefixed()
sessionId.addBytes(m.sessionId)
hello.addU16(m.cipherSuite)
hello.addU8(m.compressionMethod)
extensions := hello.addU16LengthPrefixed()
if vers >= VersionTLS13 {
if m.hasKeyShare {
if isDraft23(m.vers) {
extensions.addU16(extensionNewKeyShare)
} else {
extensions.addU16(extensionOldKeyShare)
}
keyShare := extensions.addU16LengthPrefixed()
keyShare.addU16(uint16(m.keyShare.group))
keyExchange := keyShare.addU16LengthPrefixed()
keyExchange.addBytes(m.keyShare.keyExchange)
}
if m.hasPSKIdentity {
extensions.addU16(extensionPreSharedKey)
extensions.addU16(2) // Length
extensions.addU16(m.pskIdentity)
}
extensions.addU16(extensionSupportedVersions)
extensions.addU16(2) // Length
if m.supportedVersOverride != 0 {
extensions.addU16(m.supportedVersOverride)
} else {
extensions.addU16(m.vers)
}
if len(m.customExtension) > 0 {
extensions.addU16(extensionCustom)
customExt := extensions.addU16LengthPrefixed()
customExt.addBytes([]byte(m.customExtension))
}
if len(m.unencryptedALPN) > 0 {
extensions.addU16(extensionALPN)
extension := extensions.addU16LengthPrefixed()
protocolNameList := extension.addU16LengthPrefixed()
protocolName := protocolNameList.addU8LengthPrefixed()
protocolName.addBytes([]byte(m.unencryptedALPN))
}
} else {
m.extensions.marshal(extensions)
if m.omitExtensions || m.emptyExtensions {
// Silently erasing server extensions will break the handshake. Instead,
// assert that tests which use this field also disable all features which
// would write an extension.
if extensions.len() != 0 {
panic(fmt.Sprintf("ServerHello unexpectedly contained extensions: %x, %+v", extensions.data(), m))
}
hello.discardChild()
if m.emptyExtensions {
hello.addU16(0)
}
}
}
m.raw = handshakeMsg.finish()
return m.raw
}
func (m *serverHelloMsg) unmarshal(data []byte) bool {
m.raw = data
reader := byteReader(data[4:])
if !reader.readU16(&m.vers) ||
!reader.readBytes(&m.random, 32) {
return false
}
vers, ok := wireToVersion(m.vers, m.isDTLS)
if !ok {
return false
}
if !reader.readU8LengthPrefixedBytes(&m.sessionId) ||
!reader.readU16(&m.cipherSuite) ||
!reader.readU8(&m.compressionMethod) {
return false
}
if len(reader) == 0 && m.vers < VersionTLS13 {
// Extension data is optional before TLS 1.3.
m.extensions = serverExtensions{}
m.omitExtensions = true
return true
}
var extensions byteReader
if !reader.readU16LengthPrefixed(&extensions) || len(reader) != 0 {
return false
}
// Parse out the version from supported_versions if available.
if m.vers == VersionTLS12 {
extensionsCopy := extensions
for len(extensionsCopy) > 0 {
var extension uint16
var body byteReader
if !extensionsCopy.readU16(&extension) ||
!extensionsCopy.readU16LengthPrefixed(&body) {
return false
}
if extension == extensionSupportedVersions {
if !body.readU16(&m.vers) || len(body) != 0 {
return false
}
vers, ok = wireToVersion(m.vers, m.isDTLS)
if !ok {
return false
}
}
}
}
if vers >= VersionTLS13 {
extensionKeyShare := extensionOldKeyShare
if isDraft23(m.vers) {
extensionKeyShare = extensionNewKeyShare
}
for len(extensions) > 0 {
var extension uint16
var body byteReader
if !extensions.readU16(&extension) ||
!extensions.readU16LengthPrefixed(&body) {
return false
}
switch extension {
case extensionKeyShare:
m.hasKeyShare = true
var group uint16
if !body.readU16(&group) ||
!body.readU16LengthPrefixedBytes(&m.keyShare.keyExchange) ||
len(body) != 0 {
return false
}
m.keyShare.group = CurveID(group)
case extensionPreSharedKey:
if !body.readU16(&m.pskIdentity) || len(body) != 0 {
return false
}
m.hasPSKIdentity = true
case extensionSupportedVersions:
// Parsed above.
default:
// Only allow the 3 extensions that are sent in
// the clear in TLS 1.3.
return false
}
}
} else if !m.extensions.unmarshal(extensions, vers) {
return false
}
return true
}
type encryptedExtensionsMsg struct {
raw []byte
extensions serverExtensions
empty bool
}
func (m *encryptedExtensionsMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
encryptedExtensionsMsg := newByteBuilder()
encryptedExtensionsMsg.addU8(typeEncryptedExtensions)
encryptedExtensions := encryptedExtensionsMsg.addU24LengthPrefixed()
if !m.empty {
extensions := encryptedExtensions.addU16LengthPrefixed()
m.extensions.marshal(extensions)
}
m.raw = encryptedExtensionsMsg.finish()
return m.raw
}
func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool {
m.raw = data
reader := byteReader(data[4:])
var extensions byteReader
if !reader.readU16LengthPrefixed(&extensions) || len(reader) != 0 {
return false
}
return m.extensions.unmarshal(extensions, VersionTLS13)
}
type serverExtensions struct {
nextProtoNeg bool
nextProtos []string
ocspStapling bool
ticketSupported bool
secureRenegotiation []byte
alpnProtocol string
alpnProtocolEmpty bool
duplicateExtension bool
channelIDRequested bool
extendedMasterSecret bool
srtpProtectionProfile uint16
srtpMasterKeyIdentifier string
sctList []byte
customExtension string
npnAfterAlpn bool
hasKeyShare bool
hasEarlyData bool
keyShare keyShareEntry
supportedVersion uint16
supportedPoints []uint8
supportedCurves []CurveID
serverNameAck bool
}
func (m *serverExtensions) marshal(extensions *byteBuilder) {
if m.duplicateExtension {
// Add a duplicate bogus extension at the beginning and end.
extensions.addU16(0xffff)
extensions.addU16(0) // length = 0 for empty extension
}
if m.nextProtoNeg && !m.npnAfterAlpn {
extensions.addU16(extensionNextProtoNeg)
extension := extensions.addU16LengthPrefixed()
for _, v := range m.nextProtos {
if len(v) > 255 {
v = v[:255]
}
npn := extension.addU8LengthPrefixed()
npn.addBytes([]byte(v))
}
}
if m.ocspStapling {
extensions.addU16(extensionStatusRequest)
extensions.addU16(0)
}
if m.ticketSupported {
extensions.addU16(extensionSessionTicket)
extensions.addU16(0)
}
if m.secureRenegotiation != nil {
extensions.addU16(extensionRenegotiationInfo)
extension := extensions.addU16LengthPrefixed()
secureRenego := extension.addU8LengthPrefixed()
secureRenego.addBytes(m.secureRenegotiation)
}
if len(m.alpnProtocol) > 0 || m.alpnProtocolEmpty {
extensions.addU16(extensionALPN)
extension := extensions.addU16LengthPrefixed()
protocolNameList := extension.addU16LengthPrefixed()
protocolName := protocolNameList.addU8LengthPrefixed()
protocolName.addBytes([]byte(m.alpnProtocol))
}
if m.channelIDRequested {
extensions.addU16(extensionChannelID)
extensions.addU16(0)
}
if m.duplicateExtension {
// Add a duplicate bogus extension at the beginning and end.
extensions.addU16(0xffff)
extensions.addU16(0)
}
if m.extendedMasterSecret {
extensions.addU16(extensionExtendedMasterSecret)
extensions.addU16(0)
}
if m.srtpProtectionProfile != 0 {
extensions.addU16(extensionUseSRTP)
extension := extensions.addU16LengthPrefixed()
srtpProtectionProfiles := extension.addU16LengthPrefixed()
srtpProtectionProfiles.addU16(m.srtpProtectionProfile)
srtpMki := extension.addU8LengthPrefixed()
srtpMki.addBytes([]byte(m.srtpMasterKeyIdentifier))
}
if m.sctList != nil {
extensions.addU16(extensionSignedCertificateTimestamp)
extension := extensions.addU16LengthPrefixed()
extension.addBytes(m.sctList)
}
if l := len(m.customExtension); l > 0 {
extensions.addU16(extensionCustom)
customExt := extensions.addU16LengthPrefixed()
customExt.addBytes([]byte(m.customExtension))
}
if m.nextProtoNeg && m.npnAfterAlpn {
extensions.addU16(extensionNextProtoNeg)
extension := extensions.addU16LengthPrefixed()
for _, v := range m.nextProtos {
if len(v) > 255 {
v = v[0:255]
}
npn := extension.addU8LengthPrefixed()
npn.addBytes([]byte(v))
}
}
if m.hasKeyShare {
extensions.addU16(extensionOldKeyShare)
keyShare := extensions.addU16LengthPrefixed()
keyShare.addU16(uint16(m.keyShare.group))
keyExchange := keyShare.addU16LengthPrefixed()
keyExchange.addBytes(m.keyShare.keyExchange)
}
if m.supportedVersion != 0 {
extensions.addU16(extensionSupportedVersions)
extensions.addU16(2) // Length
extensions.addU16(m.supportedVersion)
}
if len(m.supportedPoints) > 0 {
// http://tools.ietf.org/html/rfc4492#section-5.1.2
extensions.addU16(extensionSupportedPoints)
supportedPointsList := extensions.addU16LengthPrefixed()
supportedPoints := supportedPointsList.addU8LengthPrefixed()
supportedPoints.addBytes(m.supportedPoints)
}
if len(m.supportedCurves) > 0 {
// https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-4.2.4
extensions.addU16(extensionSupportedCurves)
supportedCurvesList := extensions.addU16LengthPrefixed()
supportedCurves := supportedCurvesList.addU16LengthPrefixed()
for _, curve := range m.supportedCurves {
supportedCurves.addU16(uint16(curve))
}
}
if m.hasEarlyData {
extensions.addU16(extensionEarlyData)
extensions.addBytes([]byte{0, 0})
}
if m.serverNameAck {
extensions.addU16(extensionServerName)
extensions.addU16(0) // zero length
}
}
func (m *serverExtensions) unmarshal(data byteReader, version uint16) bool {
// Reset all fields.
*m = serverExtensions{}
for len(data) > 0 {
var extension uint16
var body byteReader
if !data.readU16(&extension) ||
!data.readU16LengthPrefixed(&body) {
return false
}
switch extension {
case extensionNextProtoNeg:
m.nextProtoNeg = true
for len(body) > 0 {
var protocol []byte
if !body.readU8LengthPrefixedBytes(&protocol) {
return false
}
m.nextProtos = append(m.nextProtos, string(protocol))
}
case extensionStatusRequest:
if len(body) != 0 {
return false
}
m.ocspStapling = true
case extensionSessionTicket:
if len(body) != 0 {
return false
}
m.ticketSupported = true
case extensionRenegotiationInfo:
if !body.readU8LengthPrefixedBytes(&m.secureRenegotiation) || len(body) != 0 {
return false
}
case extensionALPN:
var protocols, protocol byteReader
if !body.readU16LengthPrefixed(&protocols) ||
len(body) != 0 ||
!protocols.readU8LengthPrefixed(&protocol) ||
len(protocols) != 0 {
return false
}
m.alpnProtocol = string(protocol)
m.alpnProtocolEmpty = len(protocol) == 0
case extensionChannelID:
if len(body) != 0 {
return false
}
m.channelIDRequested = true
case extensionExtendedMasterSecret:
if len(body) != 0 {
return false
}
m.extendedMasterSecret = true
case extensionUseSRTP:
var profiles, mki byteReader
if !body.readU16LengthPrefixed(&profiles) ||
!profiles.readU16(&m.srtpProtectionProfile) ||
len(profiles) != 0 ||
!body.readU8LengthPrefixed(&mki) ||
len(body) != 0 {
return false
}
m.srtpMasterKeyIdentifier = string(mki)
case extensionSignedCertificateTimestamp:
m.sctList = []byte(body)
case extensionCustom:
m.customExtension = string(body)
case extensionServerName:
if len(body) != 0 {
return false
}
m.serverNameAck = true
case extensionSupportedPoints:
// supported_points is illegal in TLS 1.3.
if version >= VersionTLS13 {
return false
}
// http://tools.ietf.org/html/rfc4492#section-5.5.2
if !body.readU8LengthPrefixedBytes(&m.supportedPoints) || len(body) != 0 {
return false
}
case extensionSupportedCurves:
// The server can only send supported_curves in TLS 1.3.
if version < VersionTLS13 {
return false
}
case extensionEarlyData:
if version < VersionTLS13 || len(body) != 0 {
return false
}
m.hasEarlyData = true
default:
// Unknown extensions are illegal from the server.
return false
}
}
return true
}
type helloRetryRequestMsg struct {
raw []byte
vers uint16
isServerHello bool
sessionId []byte
cipherSuite uint16
compressionMethod uint8
hasSelectedGroup bool
selectedGroup CurveID
cookie []byte
customExtension string
duplicateExtensions bool
}
func (m *helloRetryRequestMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
retryRequestMsg := newByteBuilder()
if isDraft22(m.vers) {
retryRequestMsg.addU8(typeServerHello)
} else {
retryRequestMsg.addU8(typeHelloRetryRequest)
}
retryRequest := retryRequestMsg.addU24LengthPrefixed()
if isDraft22(m.vers) {
retryRequest.addU16(VersionTLS12)
retryRequest.addBytes(tls13HelloRetryRequest)
sessionId := retryRequest.addU8LengthPrefixed()
sessionId.addBytes(m.sessionId)
retryRequest.addU16(m.cipherSuite)
retryRequest.addU8(m.compressionMethod)
} else {
retryRequest.addU16(m.vers)
if isDraft22(m.vers) {
retryRequest.addU16(m.cipherSuite)
}
}
extensions := retryRequest.addU16LengthPrefixed()
count := 1
if m.duplicateExtensions {
count = 2
}
for i := 0; i < count; i++ {
if isDraft22(m.vers) {
extensions.addU16(extensionSupportedVersions)
extensions.addU16(2) // Length
extensions.addU16(m.vers)
}
if m.hasSelectedGroup {
if isDraft23(m.vers) {
extensions.addU16(extensionNewKeyShare)
} else {
extensions.addU16(extensionOldKeyShare)
}
extensions.addU16(2) // length
extensions.addU16(uint16(m.selectedGroup))
}
// m.cookie may be a non-nil empty slice for empty cookie tests.
if m.cookie != nil {
extensions.addU16(extensionCookie)
body := extensions.addU16LengthPrefixed()
body.addU16LengthPrefixed().addBytes(m.cookie)
}
if len(m.customExtension) > 0 {
extensions.addU16(extensionCustom)
extensions.addU16LengthPrefixed().addBytes([]byte(m.customExtension))
}
}
m.raw = retryRequestMsg.finish()
return m.raw
}
func (m *helloRetryRequestMsg) unmarshal(data []byte) bool {
m.raw = data
reader := byteReader(data[4:])
if !reader.readU16(&m.vers) {
return false
}
if m.isServerHello {
var random []byte
var compressionMethod byte
if !reader.readBytes(&random, 32) ||
!reader.readU8LengthPrefixedBytes(&m.sessionId) ||
!reader.readU16(&m.cipherSuite) ||
!reader.readU8(&compressionMethod) ||
compressionMethod != 0 {
return false
}
} else if isDraft22(m.vers) && !reader.readU16(&m.cipherSuite) {
return false
}
var extensions byteReader
if !reader.readU16LengthPrefixed(&extensions) || len(reader) != 0 {
return false
}
extensionsCopy := extensions
for len(extensionsCopy) > 0 {
var extension uint16
var body byteReader
if !extensionsCopy.readU16(&extension) ||
!extensionsCopy.readU16LengthPrefixed(&body) {
return false
}
switch extension {
case extensionSupportedVersions:
if !m.isServerHello ||
!body.readU16(&m.vers) ||
len(body) != 0 {
return false
}
default:
}
}
extensionKeyShare := extensionOldKeyShare
if isDraft23(m.vers) {
extensionKeyShare = extensionNewKeyShare
}
for len(extensions) > 0 {
var extension uint16
var body byteReader
if !extensions.readU16(&extension) ||
!extensions.readU16LengthPrefixed(&body) {
return false
}
switch extension {
case extensionSupportedVersions:
// Parsed above.
case extensionKeyShare:
var v uint16
if !body.readU16(&v) || len(body) != 0 {
return false
}
m.hasSelectedGroup = true
m.selectedGroup = CurveID(v)
case extensionCookie:
if !body.readU16LengthPrefixedBytes(&m.cookie) || len(body) != 0 {
return false
}
default:
// Unknown extensions are illegal from the server.
return false
}
}
return true
}
type certificateEntry struct {
data []byte
ocspResponse []byte
sctList []byte
duplicateExtensions bool
extraExtension []byte
}
type certificateMsg struct {
raw []byte
hasRequestContext bool
requestContext []byte
certificates []certificateEntry
}
func (m *certificateMsg) marshal() (x []byte) {
if m.raw != nil {
return m.raw
}
certMsg := newByteBuilder()
certMsg.addU8(typeCertificate)
certificate := certMsg.addU24LengthPrefixed()
if m.hasRequestContext {
context := certificate.addU8LengthPrefixed()
context.addBytes(m.requestContext)
}
certificateList := certificate.addU24LengthPrefixed()
for _, cert := range m.certificates {
certEntry := certificateList.addU24LengthPrefixed()
certEntry.addBytes(cert.data)
if m.hasRequestContext {
extensions := certificateList.addU16LengthPrefixed()
count := 1
if cert.duplicateExtensions {
count = 2
}
for i := 0; i < count; i++ {
if cert.ocspResponse != nil {
extensions.addU16(extensionStatusRequest)
body := extensions.addU16LengthPrefixed()
body.addU8(statusTypeOCSP)
response := body.addU24LengthPrefixed()
response.addBytes(cert.ocspResponse)
}
if cert.sctList != nil {
extensions.addU16(extensionSignedCertificateTimestamp)
extension := extensions.addU16LengthPrefixed()
extension.addBytes(cert.sctList)
}
}
if cert.extraExtension != nil {
extensions.addBytes(cert.extraExtension)
}
}
}
m.raw = certMsg.finish()
return m.raw
}
func (m *certificateMsg) unmarshal(data []byte) bool {
m.raw = data
reader := byteReader(data[4:])
if m.hasRequestContext && !reader.readU8LengthPrefixedBytes(&m.requestContext) {
return false
}
var certs byteReader
if !reader.readU24LengthPrefixed(&certs) || len(reader) != 0 {
return false
}
m.certificates = nil
for len(certs) > 0 {
var cert certificateEntry
if !certs.readU24LengthPrefixedBytes(&cert.data) {
return false
}
if m.hasRequestContext {
var extensions byteReader
if !certs.readU16LengthPrefixed(&extensions) {
return false
}
for len(extensions) > 0 {
var extension uint16
var body byteReader
if !extensions.readU16(&extension) ||
!extensions.readU16LengthPrefixed(&body) {
return false
}
switch extension {
case extensionStatusRequest:
var statusType byte
if !body.readU8(&statusType) ||
statusType != statusTypeOCSP ||
!body.readU24LengthPrefixedBytes(&cert.ocspResponse) ||
len(body) != 0 {
return false
}
case extensionSignedCertificateTimestamp:
cert.sctList = []byte(body)
default:
return false
}
}
}
m.certificates = append(m.certificates, cert)
}
return true
}
type serverKeyExchangeMsg struct {
raw []byte
key []byte
}
func (m *serverKeyExchangeMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
msg := newByteBuilder()
msg.addU8(typeServerKeyExchange)
msg.addU24LengthPrefixed().addBytes(m.key)
m.raw = msg.finish()
return m.raw
}
func (m *serverKeyExchangeMsg) unmarshal(data []byte) bool {
m.raw = data
if len(data) < 4 {
return false
}
m.key = data[4:]
return true
}
type certificateStatusMsg struct {
raw []byte
statusType uint8
response []byte
}
func (m *certificateStatusMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
var x []byte
if m.statusType == statusTypeOCSP {
msg := newByteBuilder()
msg.addU8(typeCertificateStatus)
body := msg.addU24LengthPrefixed()
body.addU8(statusTypeOCSP)
body.addU24LengthPrefixed().addBytes(m.response)
x = msg.finish()
} else {
x = []byte{typeCertificateStatus, 0, 0, 1, m.statusType}
}
m.raw = x
return x
}
func (m *certificateStatusMsg) unmarshal(data []byte) bool {
m.raw = data
reader := byteReader(data[4:])
if !reader.readU8(&m.statusType) ||
m.statusType != statusTypeOCSP ||
!reader.readU24LengthPrefixedBytes(&m.response) ||
len(reader) != 0 {
return false
}
return true
}
type serverHelloDoneMsg struct{}
func (m *serverHelloDoneMsg) marshal() []byte {
x := make([]byte, 4)
x[0] = typeServerHelloDone
return x
}
func (m *serverHelloDoneMsg) unmarshal(data []byte) bool {
return len(data) == 4
}
type clientKeyExchangeMsg struct {
raw []byte
ciphertext []byte
}
func (m *clientKeyExchangeMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
msg := newByteBuilder()
msg.addU8(typeClientKeyExchange)
msg.addU24LengthPrefixed().addBytes(m.ciphertext)
m.raw = msg.finish()
return m.raw
}
func (m *clientKeyExchangeMsg) unmarshal(data []byte) bool {
m.raw = data
if len(data) < 4 {
return false
}
l := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
if l != len(data)-4 {
return false
}
m.ciphertext = data[4:]
return true
}
type finishedMsg struct {
raw []byte
verifyData []byte
}
func (m *finishedMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
msg := newByteBuilder()
msg.addU8(typeFinished)
msg.addU24LengthPrefixed().addBytes(m.verifyData)
m.raw = msg.finish()
return m.raw
}
func (m *finishedMsg) unmarshal(data []byte) bool {
m.raw = data
if len(data) < 4 {
return false
}
m.verifyData = data[4:]
return true
}
type nextProtoMsg struct {
raw []byte
proto string
}
func (m *nextProtoMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
padding := 32 - (len(m.proto)+2)%32
msg := newByteBuilder()
msg.addU8(typeNextProtocol)
body := msg.addU24LengthPrefixed()
body.addU8LengthPrefixed().addBytes([]byte(m.proto))
body.addU8LengthPrefixed().addBytes(make([]byte, padding))
m.raw = msg.finish()
return m.raw
}
func (m *nextProtoMsg) unmarshal(data []byte) bool {
m.raw = data
reader := byteReader(data[4:])
var proto, padding []byte
if !reader.readU8LengthPrefixedBytes(&proto) ||
!reader.readU8LengthPrefixedBytes(&padding) ||
len(reader) != 0 {
return false
}
m.proto = string(proto)
// Padding is not meant to be checked normally, but as this is a testing
// implementation, we check the padding is as expected.
if len(padding) != 32-(len(m.proto)+2)%32 {
return false
}
for _, v := range padding {
if v != 0 {
return false
}
}
return true
}
type certificateRequestMsg struct {
raw []byte
vers uint16
// hasSignatureAlgorithm indicates whether this message includes a list
// of signature and hash functions. This change was introduced with TLS
// 1.2.
hasSignatureAlgorithm bool
// hasRequestContext indicates whether this message includes a context
// field instead of certificateTypes. This change was introduced with
// TLS 1.3.
hasRequestContext bool
certificateTypes []byte
requestContext []byte
signatureAlgorithms []signatureAlgorithm
certificateAuthorities [][]byte
hasCAExtension bool
customExtension uint16
}
func (m *certificateRequestMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
// See http://tools.ietf.org/html/rfc4346#section-7.4.4
builder := newByteBuilder()
builder.addU8(typeCertificateRequest)
body := builder.addU24LengthPrefixed()
if m.hasRequestContext {
requestContext := body.addU8LengthPrefixed()
requestContext.addBytes(m.requestContext)
extensions := newByteBuilder()
if isDraft22(m.vers) {
extensions = body.addU16LengthPrefixed()
if m.hasSignatureAlgorithm {
extensions.addU16(extensionSignatureAlgorithms)
signatureAlgorithms := extensions.addU16LengthPrefixed().addU16LengthPrefixed()
for _, sigAlg := range m.signatureAlgorithms {
signatureAlgorithms.addU16(uint16(sigAlg))
}
}
if len(m.certificateAuthorities) > 0 {
extensions.addU16(extensionCertificateAuthorities)
certificateAuthorities := extensions.addU16LengthPrefixed().addU16LengthPrefixed()
for _, ca := range m.certificateAuthorities {
caEntry := certificateAuthorities.addU16LengthPrefixed()
caEntry.addBytes(ca)
}
}
} else {
if m.hasSignatureAlgorithm {
signatureAlgorithms := body.addU16LengthPrefixed()
for _, sigAlg := range m.signatureAlgorithms {
signatureAlgorithms.addU16(uint16(sigAlg))
}
}
certificateAuthorities := body.addU16LengthPrefixed()
for _, ca := range m.certificateAuthorities {
caEntry := certificateAuthorities.addU16LengthPrefixed()
caEntry.addBytes(ca)
}
extensions = body.addU16LengthPrefixed()
}
if m.customExtension > 0 {
extensions.addU16(m.customExtension)
extensions.addU16LengthPrefixed()
}
} else {
certificateTypes := body.addU8LengthPrefixed()
certificateTypes.addBytes(m.certificateTypes)
if m.hasSignatureAlgorithm {
signatureAlgorithms := body.addU16LengthPrefixed()
for _, sigAlg := range m.signatureAlgorithms {
signatureAlgorithms.addU16(uint16(sigAlg))
}
}
certificateAuthorities := body.addU16LengthPrefixed()
for _, ca := range m.certificateAuthorities {
caEntry := certificateAuthorities.addU16LengthPrefixed()
caEntry.addBytes(ca)
}
}
m.raw = builder.finish()
return m.raw
}
func parseCAs(reader *byteReader, out *[][]byte) bool {
var cas byteReader
if !reader.readU16LengthPrefixed(&cas) {
return false
}
for len(cas) > 0 {
var ca []byte
if !cas.readU16LengthPrefixedBytes(&ca) {
return false
}
*out = append(*out, ca)
}
return true
}
func (m *certificateRequestMsg) unmarshal(data []byte) bool {
m.raw = data
reader := byteReader(data[4:])
if isDraft22(m.vers) {
var extensions byteReader
if !reader.readU8LengthPrefixedBytes(&m.requestContext) ||
!reader.readU16LengthPrefixed(&extensions) ||
len(reader) != 0 {
return false
}
for len(extensions) > 0 {
var extension uint16
var body byteReader
if !extensions.readU16(&extension) ||
!extensions.readU16LengthPrefixed(&body) {
return false
}
switch extension {
case extensionSignatureAlgorithms:
if !parseSignatureAlgorithms(&body, &m.signatureAlgorithms) || len(body) != 0 {
return false
}
case extensionCertificateAuthorities:
if !parseCAs(&body, &m.certificateAuthorities) || len(body) != 0 {
return false
}
m.hasCAExtension = true
}
}
} else if m.hasRequestContext {
var extensions byteReader
if !reader.readU8LengthPrefixedBytes(&m.requestContext) ||
!parseSignatureAlgorithms(&reader, &m.signatureAlgorithms) ||
!parseCAs(&reader, &m.certificateAuthorities) ||
!reader.readU16LengthPrefixed(&extensions) ||
len(reader) != 0 {
return false
}
// Ignore certificate extensions.
} else {
if !reader.readU8LengthPrefixedBytes(&m.certificateTypes) {
return false
}
if m.hasSignatureAlgorithm && !parseSignatureAlgorithms(&reader, &m.signatureAlgorithms) {
return false
}
if !parseCAs(&reader, &m.certificateAuthorities) ||
len(reader) != 0 {
return false
}
}
return true
}
type certificateVerifyMsg struct {
raw []byte
hasSignatureAlgorithm bool
signatureAlgorithm signatureAlgorithm
signature []byte
}
func (m *certificateVerifyMsg) marshal() (x []byte) {
if m.raw != nil {
return m.raw
}
// See http://tools.ietf.org/html/rfc4346#section-7.4.8
siglength := len(m.signature)
length := 2 + siglength
if m.hasSignatureAlgorithm {
length += 2
}
x = make([]byte, 4+length)
x[0] = typeCertificateVerify
x[1] = uint8(length >> 16)
x[2] = uint8(length >> 8)
x[3] = uint8(length)
y := x[4:]
if m.hasSignatureAlgorithm {
y[0] = byte(m.signatureAlgorithm >> 8)
y[1] = byte(m.signatureAlgorithm)
y = y[2:]
}
y[0] = uint8(siglength >> 8)
y[1] = uint8(siglength)
copy(y[2:], m.signature)
m.raw = x
return
}
func (m *certificateVerifyMsg) unmarshal(data []byte) bool {
m.raw = data
if len(data) < 6 {
return false
}
length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
if uint32(len(data))-4 != length {
return false
}
data = data[4:]
if m.hasSignatureAlgorithm {
m.signatureAlgorithm = signatureAlgorithm(data[0])<<8 | signatureAlgorithm(data[1])
data = data[2:]
}
if len(data) < 2 {
return false
}
siglength := int(data[0])<<8 + int(data[1])
data = data[2:]
if len(data) != siglength {
return false
}
m.signature = data
return true
}
type newSessionTicketMsg struct {
raw []byte
vers uint16
isDTLS bool
ticketLifetime uint32
ticketAgeAdd uint32
ticketNonce []byte
ticket []byte
maxEarlyDataSize uint32
customExtension string
duplicateEarlyDataExtension bool
hasGREASEExtension bool
}
func (m *newSessionTicketMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
version, ok := wireToVersion(m.vers, m.isDTLS)
if !ok {
panic("unknown version")
}
// See http://tools.ietf.org/html/rfc5077#section-3.3
ticketMsg := newByteBuilder()
ticketMsg.addU8(typeNewSessionTicket)
body := ticketMsg.addU24LengthPrefixed()
body.addU32(m.ticketLifetime)
if version >= VersionTLS13 {
body.addU32(m.ticketAgeAdd)
if isDraft22(m.vers) {
body.addU8LengthPrefixed().addBytes(m.ticketNonce)
}
}
ticket := body.addU16LengthPrefixed()
ticket.addBytes(m.ticket)
if version >= VersionTLS13 {
extensions := body.addU16LengthPrefixed()
if m.maxEarlyDataSize > 0 {
extID := extensionTicketEarlyDataInfo
if isDraft22(m.vers) {
extID = extensionEarlyData
}
extensions.addU16(extID)
extensions.addU16LengthPrefixed().addU32(m.maxEarlyDataSize)
if m.duplicateEarlyDataExtension {
extensions.addU16(extID)
extensions.addU16LengthPrefixed().addU32(m.maxEarlyDataSize)
}
}
if len(m.customExtension) > 0 {
extensions.addU16(extensionCustom)
extensions.addU16LengthPrefixed().addBytes([]byte(m.customExtension))
}
}
m.raw = ticketMsg.finish()
return m.raw
}
func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
m.raw = data
version, ok := wireToVersion(m.vers, m.isDTLS)
if !ok {
panic("unknown version")
}
if len(data) < 8 {
return false
}
m.ticketLifetime = uint32(data[4])<<24 | uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7])
data = data[8:]
if version >= VersionTLS13 {
if len(data) < 4 {
return false
}
m.ticketAgeAdd = uint32(data[0])<<24 | uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
data = data[4:]
if isDraft22(m.vers) {
nonceLen := int(data[0])
data = data[1:]
if len(data) < nonceLen {
return false
}
m.ticketNonce = data[:nonceLen]
data = data[nonceLen:]
}
}
if len(data) < 2 {
return false
}
ticketLen := int(data[0])<<8 + int(data[1])
data = data[2:]
if len(data) < ticketLen {
return false
}
if version >= VersionTLS13 && ticketLen == 0 {
return false
}
m.ticket = data[:ticketLen]
data = data[ticketLen:]
if version >= VersionTLS13 {
if len(data) < 2 {
return false
}
extensionsLength := int(data[0])<<8 | int(data[1])
data = data[2:]
if extensionsLength != len(data) {
return false
}
extID := extensionTicketEarlyDataInfo
if isDraft22(m.vers) {
extID = extensionEarlyData
}
for len(data) != 0 {
if len(data) < 4 {
return false
}
extension := uint16(data[0])<<8 | uint16(data[1])
length := int(data[2])<<8 | int(data[3])
data = data[4:]
if len(data) < length {
return false
}
switch extension {
case extID:
if length != 4 {
return false
}
m.maxEarlyDataSize = uint32(data[0])<<24 | uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
default:
if isGREASEValue(extension) {
m.hasGREASEExtension = true
}
}
data = data[length:]
}
}
if len(data) > 0 {
return false
}
return true
}
type v2ClientHelloMsg struct {
raw []byte
vers uint16
cipherSuites []uint16
sessionId []byte
challenge []byte
}
func (m *v2ClientHelloMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
length := 1 + 2 + 2 + 2 + 2 + len(m.cipherSuites)*3 + len(m.sessionId) + len(m.challenge)
x := make([]byte, length)
x[0] = 1
x[1] = uint8(m.vers >> 8)
x[2] = uint8(m.vers)
x[3] = uint8((len(m.cipherSuites) * 3) >> 8)
x[4] = uint8(len(m.cipherSuites) * 3)
x[5] = uint8(len(m.sessionId) >> 8)
x[6] = uint8(len(m.sessionId))
x[7] = uint8(len(m.challenge) >> 8)
x[8] = uint8(len(m.challenge))
y := x[9:]
for i, spec := range m.cipherSuites {
y[i*3] = 0
y[i*3+1] = uint8(spec >> 8)
y[i*3+2] = uint8(spec)
}
y = y[len(m.cipherSuites)*3:]
copy(y, m.sessionId)
y = y[len(m.sessionId):]
copy(y, m.challenge)
m.raw = x
return x
}
type helloVerifyRequestMsg struct {
raw []byte
vers uint16
cookie []byte
}
func (m *helloVerifyRequestMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
length := 2 + 1 + len(m.cookie)
x := make([]byte, 4+length)
x[0] = typeHelloVerifyRequest
x[1] = uint8(length >> 16)
x[2] = uint8(length >> 8)
x[3] = uint8(length)
vers := m.vers
x[4] = uint8(vers >> 8)
x[5] = uint8(vers)
x[6] = uint8(len(m.cookie))
copy(x[7:7+len(m.cookie)], m.cookie)
return x
}
func (m *helloVerifyRequestMsg) unmarshal(data []byte) bool {
if len(data) < 4+2+1 {
return false
}
m.raw = data
m.vers = uint16(data[4])<<8 | uint16(data[5])
cookieLen := int(data[6])
if cookieLen > 32 || len(data) != 7+cookieLen {
return false
}
m.cookie = data[7 : 7+cookieLen]
return true
}
type channelIDMsg struct {
raw []byte
channelID []byte
}
func (m *channelIDMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
length := 2 + 2 + len(m.channelID)
x := make([]byte, 4+length)
x[0] = typeChannelID
x[1] = uint8(length >> 16)
x[2] = uint8(length >> 8)
x[3] = uint8(length)
x[4] = uint8(extensionChannelID >> 8)
x[5] = uint8(extensionChannelID & 0xff)
x[6] = uint8(len(m.channelID) >> 8)
x[7] = uint8(len(m.channelID) & 0xff)
copy(x[8:], m.channelID)
return x
}
func (m *channelIDMsg) unmarshal(data []byte) bool {
if len(data) != 4+2+2+128 {
return false
}
m.raw = data
if (uint16(data[4])<<8)|uint16(data[5]) != extensionChannelID {
return false
}
if int(data[6])<<8|int(data[7]) != 128 {
return false
}
m.channelID = data[4+2+2:]
return true
}
type helloRequestMsg struct {
}
func (*helloRequestMsg) marshal() []byte {
return []byte{typeHelloRequest, 0, 0, 0}
}
func (*helloRequestMsg) unmarshal(data []byte) bool {
return len(data) == 4
}
type keyUpdateMsg struct {
raw []byte
keyUpdateRequest byte
}
func (m *keyUpdateMsg) marshal() []byte {
if m.raw != nil {
return m.raw
}
return []byte{typeKeyUpdate, 0, 0, 1, m.keyUpdateRequest}
}
func (m *keyUpdateMsg) unmarshal(data []byte) bool {
m.raw = data
if len(data) != 5 {
return false
}
length := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
if len(data)-4 != length {
return false
}
m.keyUpdateRequest = data[4]
return m.keyUpdateRequest == keyUpdateNotRequested || m.keyUpdateRequest == keyUpdateRequested
}
type endOfEarlyDataMsg struct {
nonEmpty bool
}
func (m *endOfEarlyDataMsg) marshal() []byte {
if m.nonEmpty {
return []byte{typeEndOfEarlyData, 0, 0, 1, 42}
}
return []byte{typeEndOfEarlyData, 0, 0, 0}
}
func (*endOfEarlyDataMsg) unmarshal(data []byte) bool {
return len(data) == 4
}
// ssl3NoCertificateMsg is a dummy message to handle SSL 3.0 using a warning
// alert in the handshake.
type ssl3NoCertificateMsg struct{}
func eqUint16s(x, y []uint16) bool {
if len(x) != len(y) {
return false
}
for i, v := range x {
if y[i] != v {
return false
}
}
return true
}
func eqCurveIDs(x, y []CurveID) bool {
if len(x) != len(y) {
return false
}
for i, v := range x {
if y[i] != v {
return false
}
}
return true
}
func eqStrings(x, y []string) bool {
if len(x) != len(y) {
return false
}
for i, v := range x {
if y[i] != v {
return false
}
}
return true
}
func eqByteSlices(x, y [][]byte) bool {
if len(x) != len(y) {
return false
}
for i, v := range x {
if !bytes.Equal(v, y[i]) {
return false
}
}
return true
}
func eqSignatureAlgorithms(x, y []signatureAlgorithm) bool {
if len(x) != len(y) {
return false
}
for i, v := range x {
v2 := y[i]
if v != v2 {
return false
}
}
return true
}
func eqKeyShareEntryLists(x, y []keyShareEntry) bool {
if len(x) != len(y) {
return false
}
for i, v := range x {
if y[i].group != v.group || !bytes.Equal(y[i].keyExchange, v.keyExchange) {
return false
}
}
return true
}
func eqPSKIdentityLists(x, y []pskIdentity) bool {
if len(x) != len(y) {
return false
}
for i, v := range x {
if !bytes.Equal(y[i].ticket, v.ticket) || y[i].obfuscatedTicketAge != v.obfuscatedTicketAge {
return false
}
}
return true
}