route/vendor/github.com/bifurcation/mint/handshake-messages_test.go

689 lines
24 KiB
Go

package mint
import (
"bytes"
"crypto/x509"
"encoding/hex"
"testing"
)
const (
fixedClientHelloBodyLen = 39
fixedServerHelloBodyLen = 36
maxCipherSuites = 1 << 15
maxExtensionDataLen = (1 << 16) - 1
maxCertRequestContextLen = 255
maxTicketLen = (1 << 16) - 1
)
var (
supportedVersionHex = hex.EncodeToString([]byte{
byte(supportedVersion >> 8),
byte(supportedVersion & 0xff),
})
tls12VersionHex = hex.EncodeToString([]byte{
byte(tls12Version >> 8),
byte(tls12Version & 0xff),
})
// ClientHello test cases
// NB: Borrowing some values from extensions_test.go
helloRandom = [32]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37}
chCipherSuites = []CipherSuite{0x0001, 0x0002, 0x0003}
chValidIn = ClientHelloBody{
Random: helloRandom,
CipherSuites: chCipherSuites,
Extensions: extListValidIn,
LegacySessionID: []byte{},
}
chValidHex = "0303" + hex.EncodeToString(helloRandom[:]) + "00" +
"0006000100020003" + "0100" + extListValidHex
chOverflowHex = "0303" + hex.EncodeToString(helloRandom[:]) + "00" +
"0006000100020003" + "0100" + extListOverflowOuterHex
// ClientHello truncation test cases
chTruncPSKData = unhex(pskClientHex)
chTruncHex = "01000062" + "0303" + hex.EncodeToString(helloRandom[:]) +
"00" + "0006000100020003" + "0100" + "00330029002f000a00040102030405060708"
chTruncValid = ClientHelloBody{
Random: helloRandom,
CipherSuites: chCipherSuites,
Extensions: []Extension{
{
ExtensionType: ExtensionTypePreSharedKey,
ExtensionData: chTruncPSKData,
},
},
}
chTruncInvalid = ClientHelloBody{}
chTruncNoExt = ClientHelloBody{
Random: helloRandom,
CipherSuites: chCipherSuites,
Extensions: []Extension{},
}
chTruncNoPSK = ClientHelloBody{
Random: helloRandom,
CipherSuites: chCipherSuites,
Extensions: []Extension{
{ExtensionType: ExtensionTypeEarlyData},
},
}
chTruncBadPSK = ClientHelloBody{
Random: helloRandom,
CipherSuites: chCipherSuites,
Extensions: []Extension{
{ExtensionType: ExtensionTypePreSharedKey},
},
}
// ServerHello test cases
shValidIn = ServerHelloBody{
Version: tls12Version,
Random: helloRandom,
LegacySessionID: []byte{},
CipherSuite: CipherSuite(0x0001),
Extensions: extListValidIn,
}
shEmptyIn = ServerHelloBody{
Version: tls12Version,
Random: helloRandom,
CipherSuite: CipherSuite(0x0001),
}
shValidHex = tls12VersionHex + hex.EncodeToString(helloRandom[:]) + "00" + "0001" + "00" + extListValidHex
shEmptyHex = tls12VersionHex + hex.EncodeToString(helloRandom[:]) + "00" + "0001" + "00" + "0000"
shOverflowHex = tls12VersionHex + hex.EncodeToString(helloRandom[:]) + "0001" + extListOverflowOuterHex
// Finished test cases
finValidIn = FinishedBody{
VerifyDataLen: len(helloRandom),
VerifyData: helloRandom[:],
}
finValidHex = hex.EncodeToString(helloRandom[:])
// EncryptedExtensions test cases
encExtValidIn = EncryptedExtensionsBody{extListValidIn}
encExtValidHex = extListValidHex
// Certificate test cases
cert1Hex = "308201653082010ba003020102020500a0a0a0a0300a0608" +
"2a8648ce3d0403023017311530130603550403130c657861" +
"6d706c65312e636f6d3022180f3030303130313031303030" +
"3030305a180f30303031303130313030303030305a301731" +
"1530130603550403130c6578616d706c65312e636f6d3059" +
"301306072a8648ce3d020106082a8648ce3d030107034200" +
"044460e6de2a170e0c7c8d1306c82386db31980bd76647bd" +
"e9b96055d075fc64ea7d8d3864afcf0ff16da73c68df6880" +
"a597303243410016ef2e36f5962584d187a340303e300e06" +
"03551d0f0101ff0404030203a830130603551d25040c300a" +
"06082b0601050507030130170603551d110410300e820c65" +
"78616d706c65312e636f6d300a06082a8648ce3d04030203" +
"48003045022005937d0bf7a7cb4589715bb83dddd2505335" +
"829e6305b75cfeae6f2dcc2230b6022100f6f0e75436cd59" +
"b94ceedffb18bcf5bb2f161260a282f7b63d1376e5805c51" +
"b6"
cert2Hex = "308201643082010ba003020102020500a0a0a0a0300a0608" +
"2a8648ce3d0403043017311530130603550403130c657861" +
"6d706c65322e636f6d3022180f3030303130313031303030" +
"3030305a180f30303031303130313030303030305a301731" +
"1530130603550403130c6578616d706c65322e636f6d3059" +
"301306072a8648ce3d020106082a8648ce3d030107034200" +
"044460e6de2a170e0c7c8d1306c82386db31980bd76647bd" +
"e9b96055d075fc64ea7d8d3864afcf0ff16da73c68df6880" +
"a597303243410016ef2e36f5962584d187a340303e300e06" +
"03551d0f0101ff0404030203a830130603551d25040c300a" +
"06082b0601050507030130170603551d110410300e820c65" +
"78616d706c65322e636f6d300a06082a8648ce3d04030403" +
"470030440220718254f2b3c1cc0fa4c53bf43182f8acbc19" +
"04e45ee1a3abdc8bc50a155712b4022010664cc29b80fae9" +
"150027726da5b144df764a76007eee2a52b6ae0c995395fb"
cert1Bytes = unhex(cert1Hex)
cert2Bytes = unhex(cert2Hex)
cert1, _ = x509.ParseCertificate(cert1Bytes)
cert2, _ = x509.ParseCertificate(cert2Bytes)
certValidIn = CertificateBody{
CertificateRequestContext: []byte{0, 0, 0, 0},
CertificateList: []CertificateEntry{
{
CertData: cert1,
Extensions: extListValidIn,
},
{
CertData: cert2,
Extensions: extListValidIn,
},
},
}
certOverflowIn = CertificateBody{
CertificateRequestContext: []byte{0, 0, 0, 0},
CertificateList: []CertificateEntry{
{
CertData: cert1,
Extensions: extListSingleTooLongIn,
},
},
}
certValidHex = "0400000000" +
"0002f5" +
"000169" + cert1Hex + extListValidHex +
"000168" + cert2Hex + extListValidHex
certTooShortHex = "000000023081"
// CertificateVerify test cases
certVerifyValidIn = CertificateVerifyBody{
Algorithm: ECDSA_P256_SHA256,
Signature: []byte{0, 0, 0, 0},
}
certVerifyValidHex = "0403000400000000"
certVerifyCipherSuite = TLS_AES_128_GCM_SHA256
// CertificateRequest test cases
certReqValidIn = CertificateRequestBody{
CertificateRequestContext: []byte{0, 1, 2, 3, 4, 5, 6, 7},
Extensions: []Extension{
{
ExtensionType: ExtensionTypeSignatureAlgorithms,
ExtensionData: unhex("000404030503"),
},
},
}
certReqValidHex = "080001020304050607" + // context
"000a000d0006000404030503" // extensions
// NewSessionTicket test cases
ticketValidHex = "00010203" + "04050607" + "0408090a0b" + "00040c0d0e0f" + "0006eeff00021122"
ticketValidIn = NewSessionTicketBody{
TicketLifetime: 0x00010203,
TicketAgeAdd: 0x04050607,
TicketNonce: []byte{0x08, 0x09, 0x0a, 0x0b},
Ticket: []byte{0x0c, 0x0d, 0x0e, 0x0f},
Extensions: []Extension{
{
ExtensionType: 0xeeff,
ExtensionData: []byte{0x11, 0x22},
},
},
}
ticketTooBigIn = NewSessionTicketBody{
TicketLifetime: 0x00010203,
Ticket: make([]byte, maxTicketLen+1),
}
ticketExtensionsTooBigIn = NewSessionTicketBody{
Extensions: extListSingleTooLongIn,
}
// KeyUpdate test cases
keyUpdateValidHex = "01"
keyUpdateValidIn = KeyUpdateBody{
KeyUpdateRequest: KeyUpdateRequested,
}
// EndOfEarlyData test cases
endOfEarlyDataValidHex = ""
endOfEarlyDataValidIn = EndOfEarlyDataBody{}
)
func TestHandshakeMessageTypes(t *testing.T) {
assertEquals(t, ClientHelloBody{}.Type(), HandshakeTypeClientHello)
assertEquals(t, ServerHelloBody{}.Type(), HandshakeTypeServerHello)
assertEquals(t, FinishedBody{}.Type(), HandshakeTypeFinished)
assertEquals(t, EncryptedExtensionsBody{}.Type(), HandshakeTypeEncryptedExtensions)
assertEquals(t, CertificateBody{}.Type(), HandshakeTypeCertificate)
assertEquals(t, CertificateVerifyBody{}.Type(), HandshakeTypeCertificateVerify)
}
func TestClientHelloMarshalUnmarshal(t *testing.T) {
chValid := unhex(chValidHex)
chOverflow := unhex(chOverflowHex)
// Test correctness of handshake type
assertEquals(t, (ClientHelloBody{}).Type(), HandshakeTypeClientHello)
// Test successful marshal
out, err := chValidIn.Marshal()
assertNotError(t, err, "Failed to marshal a valid ClientHello")
assertByteEquals(t, out, chValid)
// Test marshal failure on empty ciphersuites
chValidIn.CipherSuites = []CipherSuite{}
out, err = chValidIn.Marshal()
assertError(t, err, "Marshaled a ClientHello with no CipherSuites")
chValidIn.CipherSuites = chCipherSuites
// Test marshal failure on too many ciphersuites
tooManyCipherSuites := make([]CipherSuite, maxCipherSuites+1)
for i := range tooManyCipherSuites {
tooManyCipherSuites[i] = CipherSuite(0x0001)
}
chValidIn.CipherSuites = tooManyCipherSuites
out, err = chValidIn.Marshal()
assertError(t, err, "Marshaled a ClientHello with too many CipherSuites")
chValidIn.CipherSuites = chCipherSuites
// Test marshal failure on extension list marshal failure
chValidIn.Extensions = extListTooLongIn
out, err = chValidIn.Marshal()
assertError(t, err, "Marshaled a ClientHello with bad extensions")
chValidIn.Extensions = extListValidIn
// Test successful unmarshal
var ch ClientHelloBody
read, err := ch.Unmarshal(chValid)
assertNotError(t, err, "Failed to unmarshal a valid ClientHello")
assertEquals(t, read, len(chValid))
assertDeepEquals(t, ch, chValidIn)
// Test unmarshal failure on too-short ClientHello
_, err = ch.Unmarshal(chValid[:fixedClientHelloBodyLen-1])
assertError(t, err, "Unmarshaled a ClientHello below the min length")
// Test unmarshal failure on wrong version
chValid[1]--
_, err = ch.Unmarshal(chValid)
assertError(t, err, "Unmarshaled a ClientHello with the wrong version")
chValid[1]++
// Test unmarshal failure on ciphersuite size overflow
chValid[35] = 0xFF
_, err = ch.Unmarshal(chValid)
assertError(t, err, "Unmarshaled a ClientHello an overflowing cipherSuite list")
chValid[35] = 0x00
// Test unmarshal failure on odd ciphersuite size
chValid[36] ^= 0x01
_, err = ch.Unmarshal(chValid)
assertError(t, err, "Unmarshaled a ClientHello an odd cipherSuite list length")
chValid[36] ^= 0x01
// Test unmarshal failure on missing compression methods
_, err = ch.Unmarshal(chValid[:37+6])
assertError(t, err, "Unmarshaled a ClientHello truncated before the compression methods")
// Test unmarshal failure on incorrect compression methods
chValid[37+6] = 0x03
_, err = ch.Unmarshal(chValid)
assertError(t, err, "Unmarshaled a ClientHello more than one compression method")
chValid[37+6] = 0x01
chValid[37+7] = 0x01
_, err = ch.Unmarshal(chValid)
assertError(t, err, "Unmarshaled a ClientHello the wrong compression method")
chValid[37+7] = 0x00
// Test unmarshal failure on extension list unmarshal failure
_, err = ch.Unmarshal(chOverflow)
assertError(t, err, "Unmarshaled a ClientHello with invalid extensions")
}
func TestClientHelloTruncate(t *testing.T) {
chTrunc := unhex(chTruncHex)
// Test success
trunc, err := chTruncValid.Truncated()
assertNotError(t, err, "Error truncating valid ClientHello")
assertByteEquals(t, trunc, chTrunc)
// Test failure on marshal failure
_, err = chTruncInvalid.Truncated()
assertError(t, err, "Truncated a ClientHello that should not have marshaled")
// Test failure on no extensions
_, err = chTruncNoExt.Truncated()
assertError(t, err, "Truncated a ClientHello with no extensions")
// Test failure on last extension not PSK
_, err = chTruncNoPSK.Truncated()
assertError(t, err, "Truncated a ClientHello whose last extension was not a PSK")
// Test failiure on last extension malformed PSK
_, err = chTruncBadPSK.Truncated()
assertError(t, err, "Truncated a ClientHello with a mal-formed PSK")
}
func TestServerHelloMarshalUnmarshal(t *testing.T) {
shValid := unhex(shValidHex)
shEmpty := unhex(shEmptyHex)
shOverflow := unhex(shOverflowHex)
// Test correctness of handshake type
assertEquals(t, (ServerHelloBody{}).Type(), HandshakeTypeServerHello)
// Test successful marshal
out, err := shValidIn.Marshal()
assertNotError(t, err, "Failed to marshal a valid ServerHello")
assertByteEquals(t, out, shValid)
// Test successful marshal with no extensions present
out, err = shEmptyIn.Marshal()
assertNotError(t, err, "Failed to marshal a valid ServerHello with no extensions")
assertByteEquals(t, out, shEmpty)
// Test marshal failure on extension list marshal failure
shValidIn.Extensions = extListTooLongIn
out, err = shValidIn.Marshal()
assertError(t, err, "Marshaled a ServerHello with bad extensions")
shValidIn.Extensions = extListValidIn
// Test successful unmarshal
var sh ServerHelloBody
read, err := sh.Unmarshal(shValid)
assertNotError(t, err, "Failed to unmarshal a valid ServerHello")
assertEquals(t, read, len(shValid))
assertDeepEquals(t, sh, shValidIn)
// Test successful unmarshal with no extensions present
read, err = sh.Unmarshal(shEmpty)
assertNotError(t, err, "Failed to unmarshal a valid ServerHello")
assertEquals(t, read, len(shEmpty))
assertByteEquals(t, sh.Random[:], shEmptyIn.Random[:])
assertEquals(t, sh.CipherSuite, shEmptyIn.CipherSuite)
assertEquals(t, len(sh.Extensions), 0)
// Test unmarshal failure on too-short ServerHello
_, err = sh.Unmarshal(shValid[:fixedServerHelloBodyLen-1])
assertError(t, err, "Unmarshaled a too-short ServerHello")
// Test unmarshal failure on extension list unmarshal failure
_, err = sh.Unmarshal(shOverflow)
assertError(t, err, "Unmarshaled a ServerHello with invalid extensions")
}
func TestFinishedMarshalUnmarshal(t *testing.T) {
finValid := unhex(finValidHex)
// Test correctness of handshake type
assertEquals(t, (FinishedBody{}).Type(), HandshakeTypeFinished)
// Test successful marshal
out, err := finValidIn.Marshal()
assertNotError(t, err, "Failed to marshal a valid Finished")
assertByteEquals(t, out, finValid)
// Test marshal failure on incorrect data length
finValidIn.VerifyDataLen--
out, err = finValidIn.Marshal()
assertError(t, err, "Marshaled a Finished with the wrong data length")
finValidIn.VerifyDataLen++
// Test successful unmarshal
var fin FinishedBody
fin.VerifyDataLen = len(finValid)
read, err := fin.Unmarshal(finValid)
assertNotError(t, err, "Failed to unmarshal a valid Finished")
assertEquals(t, read, len(finValid))
assertDeepEquals(t, fin, finValidIn)
// Test unmarshal failure on insufficient data
fin.VerifyDataLen++
_, err = fin.Unmarshal(finValid)
assertError(t, err, "Unmarshaled a Finished with too little data")
fin.VerifyDataLen--
}
// This one is a little brief because it is just an extensionList
func TestEncrypteExtensionsMarshalUnmarshal(t *testing.T) {
encExtValid := unhex(encExtValidHex)
// Test correctness of handshake type
assertEquals(t, (EncryptedExtensionsBody{}).Type(), HandshakeTypeEncryptedExtensions)
// Test successful marshal
out, err := encExtValidIn.Marshal()
assertNotError(t, err, "Failed to marshal a valid EncryptedExtensions")
assertByteEquals(t, out, encExtValid)
// Test successful unmarshal
var ee EncryptedExtensionsBody
read, err := ee.Unmarshal(encExtValid)
assertNotError(t, err, "Failed to unmarshal a valid EncryptedExtensions")
assertEquals(t, read, len(encExtValid))
assertDeepEquals(t, ee, encExtValidIn)
}
func TestCertificateMarshalUnmarshal(t *testing.T) {
// Create a couple of certificates and manually encode
certValid := unhex(certValidHex)
certTooShort := unhex(certTooShortHex)
// Test correctness of handshake type
assertEquals(t, (CertificateBody{}).Type(), HandshakeTypeCertificate)
// Test successful marshal
out, err := certValidIn.Marshal()
assertNotError(t, err, "Failed to marshal valid Certificate")
assertByteEquals(t, out, certValid)
// Test marshal failure on context too long
originalContext := certValidIn.CertificateRequestContext
certValidIn.CertificateRequestContext = bytes.Repeat([]byte{0}, maxCertRequestContextLen+1)
out, err = certValidIn.Marshal()
assertError(t, err, "Marshaled a Certificate with a too-long context")
certValidIn.CertificateRequestContext = originalContext
// Test marshal failure on no raw certa
originalRaw := cert1.Raw
cert1.Raw = []byte{}
out, err = certValidIn.Marshal()
assertError(t, err, "Marshaled a Certificate with an empty cert")
cert1.Raw = originalRaw
// Test marshal failure on extension list marshal failure
out, err = certOverflowIn.Marshal()
assertError(t, err, "Marshaled a Certificate with an too-long extension list")
// Test successful unmarshal
cert := CertificateBody{}
read, err := cert.Unmarshal(certValid)
assertNotError(t, err, "Failed to unmarshal valid Certificate")
assertEquals(t, read, len(certValid))
assertDeepEquals(t, cert, certValidIn)
// Test unmarshal failure on truncated header
_, err = cert.Unmarshal(certValid[:0])
assertError(t, err, "Unmarshaled a Certificate with a truncated header")
// Test unmarshal failure on truncated context
_, err = cert.Unmarshal(certValid[:7])
assertError(t, err, "Unmarshaled a Certificate with a truncated context")
// Test unmarshal failure on truncated certificates
_, err = cert.Unmarshal(certValid[:12])
assertError(t, err, "Unmarshaled a Certificate with truncated certificates")
// Test unmarshal failure on a too-short certificates field
_, err = cert.Unmarshal(certTooShort)
assertError(t, err, "Unmarshaled a Certificate with truncated certificate length")
// Test unmarshal failure on truncated certificate
certValid[8] ^= 0xFF // Make length of first cert huge
_, err = cert.Unmarshal(certValid)
assertError(t, err, "Unmarshaled a Certificate with truncated certificates")
certValid[8] ^= 0xFF
// Test unmarshal failure on malformed certificate
certValid[11] ^= 0xFF // Clobber first octet of first cert
_, err = cert.Unmarshal(certValid)
assertError(t, err, "Unmarshaled a Certificate with truncated certificates")
certValid[11] ^= 0xFF
}
func TestCertificateVerifyMarshalUnmarshal(t *testing.T) {
certVerifyValid := unhex(certVerifyValidHex)
handshakeHash := []byte{0, 1, 2, 3}
privRSA, err := newSigningKey(RSA_PSS_SHA256)
assertNotError(t, err, "failed to generate RSA private key")
// Test correctness of handshake type
assertEquals(t, (CertificateVerifyBody{}).Type(), HandshakeTypeCertificateVerify)
// Test successful marshal
out, err := certVerifyValidIn.Marshal()
assertNotError(t, err, "Failed to marshal a valid CertificateVerify")
assertByteEquals(t, out, certVerifyValid)
// Test successful unmarshal
var cv CertificateVerifyBody
read, err := cv.Unmarshal(certVerifyValid)
assertNotError(t, err, "Failed to unmarshal a valid CertificateVerify")
assertEquals(t, read, len(certVerifyValid))
assertDeepEquals(t, cv, certVerifyValidIn)
// Test unmarshal failure on truncated header
_, err = cv.Unmarshal(certVerifyValid[:1])
assertError(t, err, "Unmarshaled a CertificateVerify with no header")
// Test unmarshal failure on truncated signature
_, err = cv.Unmarshal(certVerifyValid[:5])
assertError(t, err, "Unmarshaled a CertificateVerify with no header")
// Test successful sign / verify round-trip
certVerifyValidIn.Algorithm = RSA_PSS_SHA256
err = certVerifyValidIn.Sign(privRSA, handshakeHash)
assertNotError(t, err, "Failed to sign CertificateVerify")
// Test sign failure on algorithm
originalAlg := certVerifyValidIn.Algorithm
certVerifyValidIn.Algorithm = SignatureScheme(0)
err = certVerifyValidIn.Sign(privRSA, handshakeHash)
assertError(t, err, "Signed CertificateVerify despite bad algorithm")
certVerifyValidIn.Algorithm = originalAlg
// Test successful verify
certVerifyValidIn = CertificateVerifyBody{Algorithm: RSA_PSS_SHA256}
err = certVerifyValidIn.Sign(privRSA, handshakeHash)
assertNotError(t, err, "Failed to sign CertificateVerify")
err = certVerifyValidIn.Verify(privRSA.Public(), handshakeHash)
assertNotError(t, err, "Failed to verify CertificateVerify")
// Test verify failure on bad algorithm
originalAlg = certVerifyValidIn.Algorithm
certVerifyValidIn.Algorithm = SignatureScheme(0)
err = certVerifyValidIn.Verify(privRSA.Public(), handshakeHash)
assertError(t, err, "Verified CertificateVerify despite bad hash algorithm")
certVerifyValidIn.Algorithm = originalAlg
}
func TestCertificateRequestMarshalUnmarshal(t *testing.T) {
certReqValid := unhex(certReqValidHex)
// Test correctness of handshake type
assertEquals(t, (CertificateRequestBody{}).Type(), HandshakeTypeCertificateRequest)
// Test successful marshal
out, err := certReqValidIn.Marshal()
assertNotError(t, err, "Failed to marshal a valid CertificateRequest")
assertByteEquals(t, out, certReqValid)
// Test successful unmarshal
var cv CertificateRequestBody
read, err := cv.Unmarshal(certReqValid)
assertNotError(t, err, "Failed to unmarshal a valid CertificateRequest")
assertEquals(t, read, len(certReqValid))
assertDeepEquals(t, cv, certReqValidIn)
}
func TestNewSessionTicketMarshalUnmarshal(t *testing.T) {
ticketValid := unhex(ticketValidHex)
// Test correctness of handshake type
assertEquals(t, (NewSessionTicketBody{}).Type(), HandshakeTypeNewSessionTicket)
// Test creation of a new random ticket
tkt, err := NewSessionTicket(16, 3)
assertNotError(t, err, "Failed to create session ticket")
assertEquals(t, tkt.TicketLifetime, uint32(3))
assertEquals(t, len(tkt.Ticket), 16)
// Test successful marshal
out, err := ticketValidIn.Marshal()
assertNotError(t, err, "Failed to marshal a valid NewSessionTicket")
assertByteEquals(t, out, ticketValid)
// Test marshal failure on a ticket that's too large
out, err = ticketTooBigIn.Marshal()
assertError(t, err, "Marshaled a NewSessionTicket with an invalid data length")
// Test marshal failure on extensions too large
out, err = ticketExtensionsTooBigIn.Marshal()
assertError(t, err, "Marshaled a NewSessionTicket with extensions that are too big")
// Test successful unmarshal
read, err := tkt.Unmarshal(ticketValid)
assertNotError(t, err, "Failed to unmarshal a valid NewSessionTicket")
assertEquals(t, read, len(ticketValid))
assertDeepEquals(t, *tkt, ticketValidIn)
// Test unmarshal failure on insufficient data
_, err = tkt.Unmarshal(ticketValid[:4])
assertError(t, err, "Unmarshaled a NewSessionTicket with an incomplete header")
_, err = tkt.Unmarshal(ticketValid[:13])
assertError(t, err, "Unmarshaled a NewSessionTicket with an incomplete ticket")
_, err = tkt.Unmarshal(ticketValid[:20])
assertError(t, err, "Unmarshaled a NewSessionTicket with incomplete extensions")
}
func TestKeyUpdateMarshalUnmarshal(t *testing.T) {
keyUpdateValid := unhex(keyUpdateValidHex)
// Test correctness of handshake type
assertEquals(t, (KeyUpdateBody{}).Type(), HandshakeTypeKeyUpdate)
// Test successful marshal
out, err := keyUpdateValidIn.Marshal()
assertNotError(t, err, "Failed to marshal a valid KeyUpdate")
assertByteEquals(t, out, keyUpdateValid)
// Test successful unmarshal
var ku KeyUpdateBody
read, err := ku.Unmarshal(keyUpdateValid)
assertNotError(t, err, "Failed to unmarshal a valid KeyUpdate")
assertEquals(t, read, len(keyUpdateValid))
assertDeepEquals(t, ku, keyUpdateValidIn)
}
func TestEndOfEarlyDataMarshalUnmarshal(t *testing.T) {
endOfEarlyDataValid := unhex(endOfEarlyDataValidHex)
// Test correctness of handshake type
assertEquals(t, (EndOfEarlyDataBody{}).Type(), HandshakeTypeEndOfEarlyData)
// Test successful marshal
out, err := endOfEarlyDataValidIn.Marshal()
assertNotError(t, err, "Failed to marshal a valid KeyUpdate")
assertByteEquals(t, out, endOfEarlyDataValid)
// Test successful unmarshal
var eoed EndOfEarlyDataBody
read, err := eoed.Unmarshal(endOfEarlyDataValid)
assertNotError(t, err, "Failed to unmarshal a valid KeyUpdate")
assertEquals(t, read, len(endOfEarlyDataValid))
assertDeepEquals(t, eoed, endOfEarlyDataValidIn)
}
func TestsafeUnmarshal(t *testing.T) {
chValid := unhex(chValidHex)
tooLong := append(chValid, 0)
var ch ClientHelloBody
// Check that safeUnmarshal works normally
err := safeUnmarshal(&ch, chValid)
assertNotError(t, err, "Failed to unmarshal ClientHello")
// Test successful unmarshal
read, err := ch.Unmarshal(tooLong)
assertNotError(t, err, "Failed to unmarshal a too long ClientHello")
assertEquals(t, read, len(chValid))
assertDeepEquals(t, ch, chValidIn)
// Now test that safeUnmarshal barfs
err = safeUnmarshal(&ch, tooLong)
assertError(t, err, "Unmarshalled something too long")
}