1
// Copyright 2012 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
18
// sessionState contains the information that is serialized into a session
19
// ticket in order to later resume a connection.
20
type sessionState struct {
27
func (s *sessionState) equal(i interface{}) bool {
28
s1, ok := i.(*sessionState)
33
if s.vers != s1.vers ||
34
s.cipherSuite != s1.cipherSuite ||
35
!bytes.Equal(s.masterSecret, s1.masterSecret) {
39
if len(s.certificates) != len(s1.certificates) {
43
for i := range s.certificates {
44
if !bytes.Equal(s.certificates[i], s1.certificates[i]) {
52
func (s *sessionState) marshal() []byte {
53
length := 2 + 2 + 2 + len(s.masterSecret) + 2
54
for _, cert := range s.certificates {
55
length += 4 + len(cert)
58
ret := make([]byte, length)
60
x[0] = byte(s.vers >> 8)
62
x[2] = byte(s.cipherSuite >> 8)
63
x[3] = byte(s.cipherSuite)
64
x[4] = byte(len(s.masterSecret) >> 8)
65
x[5] = byte(len(s.masterSecret))
67
copy(x, s.masterSecret)
68
x = x[len(s.masterSecret):]
70
x[0] = byte(len(s.certificates) >> 8)
71
x[1] = byte(len(s.certificates))
74
for _, cert := range s.certificates {
75
x[0] = byte(len(cert) >> 24)
76
x[1] = byte(len(cert) >> 16)
77
x[2] = byte(len(cert) >> 8)
78
x[3] = byte(len(cert))
86
func (s *sessionState) unmarshal(data []byte) bool {
91
s.vers = uint16(data[0])<<8 | uint16(data[1])
92
s.cipherSuite = uint16(data[2])<<8 | uint16(data[3])
93
masterSecretLen := int(data[4])<<8 | int(data[5])
95
if len(data) < masterSecretLen {
99
s.masterSecret = data[:masterSecretLen]
100
data = data[masterSecretLen:]
106
numCerts := int(data[0])<<8 | int(data[1])
109
s.certificates = make([][]byte, numCerts)
110
for i := range s.certificates {
114
certLen := int(data[0])<<24 | int(data[1])<<16 | int(data[2])<<8 | int(data[3])
119
if len(data) < certLen {
122
s.certificates[i] = data[:certLen]
123
data = data[certLen:]
133
func (c *Conn) encryptTicket(state *sessionState) ([]byte, error) {
134
serialized := state.marshal()
135
encrypted := make([]byte, aes.BlockSize+len(serialized)+sha256.Size)
136
iv := encrypted[:aes.BlockSize]
137
macBytes := encrypted[len(encrypted)-sha256.Size:]
139
if _, err := io.ReadFull(c.config.rand(), iv); err != nil {
142
block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
144
return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error())
146
cipher.NewCTR(block, iv).XORKeyStream(encrypted[aes.BlockSize:], serialized)
148
mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
149
mac.Write(encrypted[:len(encrypted)-sha256.Size])
150
mac.Sum(macBytes[:0])
152
return encrypted, nil
155
func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) {
156
if len(encrypted) < aes.BlockSize+sha256.Size {
160
iv := encrypted[:aes.BlockSize]
161
macBytes := encrypted[len(encrypted)-sha256.Size:]
163
mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
164
mac.Write(encrypted[:len(encrypted)-sha256.Size])
165
expected := mac.Sum(nil)
167
if subtle.ConstantTimeCompare(macBytes, expected) != 1 {
171
block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
175
ciphertext := encrypted[aes.BlockSize : len(encrypted)-sha256.Size]
176
plaintext := ciphertext
177
cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext)
179
state := new(sessionState)
180
ok := state.unmarshal(plaintext)