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 {
26 extendedMasterSecret bool
29 func (s *sessionState) equal(i interface{}) bool {
30 s1, ok := i.(*sessionState)
35 if s.vers != s1.vers ||
36 s.cipherSuite != s1.cipherSuite ||
37 !bytes.Equal(s.masterSecret, s1.masterSecret) ||
38 !bytes.Equal(s.handshakeHash, s1.handshakeHash) ||
39 s.extendedMasterSecret != s1.extendedMasterSecret {
43 if len(s.certificates) != len(s1.certificates) {
47 for i := range s.certificates {
48 if !bytes.Equal(s.certificates[i], s1.certificates[i]) {
56 func (s *sessionState) marshal() []byte {
57 length := 2 + 2 + 2 + len(s.masterSecret) + 2 + len(s.handshakeHash) + 2
58 for _, cert := range s.certificates {
59 length += 4 + len(cert)
63 ret := make([]byte, length)
65 x[0] = byte(s.vers >> 8)
67 x[2] = byte(s.cipherSuite >> 8)
68 x[3] = byte(s.cipherSuite)
69 x[4] = byte(len(s.masterSecret) >> 8)
70 x[5] = byte(len(s.masterSecret))
72 copy(x, s.masterSecret)
73 x = x[len(s.masterSecret):]
75 x[0] = byte(len(s.handshakeHash) >> 8)
76 x[1] = byte(len(s.handshakeHash))
78 copy(x, s.handshakeHash)
79 x = x[len(s.handshakeHash):]
81 x[0] = byte(len(s.certificates) >> 8)
82 x[1] = byte(len(s.certificates))
85 for _, cert := range s.certificates {
86 x[0] = byte(len(cert) >> 24)
87 x[1] = byte(len(cert) >> 16)
88 x[2] = byte(len(cert) >> 8)
89 x[3] = byte(len(cert))
94 if s.extendedMasterSecret {
102 func (s *sessionState) unmarshal(data []byte) bool {
107 s.vers = uint16(data[0])<<8 | uint16(data[1])
108 s.cipherSuite = uint16(data[2])<<8 | uint16(data[3])
109 masterSecretLen := int(data[4])<<8 | int(data[5])
111 if len(data) < masterSecretLen {
115 s.masterSecret = data[:masterSecretLen]
116 data = data[masterSecretLen:]
122 handshakeHashLen := int(data[0])<<8 | int(data[1])
124 if len(data) < handshakeHashLen {
128 s.handshakeHash = data[:handshakeHashLen]
129 data = data[handshakeHashLen:]
135 numCerts := int(data[0])<<8 | int(data[1])
138 s.certificates = make([][]byte, numCerts)
139 for i := range s.certificates {
143 certLen := int(data[0])<<24 | int(data[1])<<16 | int(data[2])<<8 | int(data[3])
148 if len(data) < certLen {
151 s.certificates[i] = data[:certLen]
152 data = data[certLen:]
159 s.extendedMasterSecret = false
161 s.extendedMasterSecret = true
172 func (c *Conn) encryptTicket(state *sessionState) ([]byte, error) {
173 serialized := state.marshal()
174 encrypted := make([]byte, aes.BlockSize+len(serialized)+sha256.Size)
175 iv := encrypted[:aes.BlockSize]
176 macBytes := encrypted[len(encrypted)-sha256.Size:]
178 if _, err := io.ReadFull(c.config.rand(), iv); err != nil {
181 block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
183 return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error())
185 cipher.NewCTR(block, iv).XORKeyStream(encrypted[aes.BlockSize:], serialized)
187 mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
188 mac.Write(encrypted[:len(encrypted)-sha256.Size])
189 mac.Sum(macBytes[:0])
191 return encrypted, nil
194 func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) {
195 if len(encrypted) < aes.BlockSize+sha256.Size {
199 iv := encrypted[:aes.BlockSize]
200 macBytes := encrypted[len(encrypted)-sha256.Size:]
202 mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
203 mac.Write(encrypted[:len(encrypted)-sha256.Size])
204 expected := mac.Sum(nil)
206 if subtle.ConstantTimeCompare(macBytes, expected) != 1 {
210 block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
214 ciphertext := encrypted[aes.BlockSize : len(encrypted)-sha256.Size]
215 plaintext := make([]byte, len(ciphertext))
216 cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext)
218 state := new(sessionState)
219 ok := state.unmarshal(plaintext)