1
2
3
4
5 package tls
6
7 import (
8 "bytes"
9 "crypto/aes"
10 "crypto/cipher"
11 "crypto/hmac"
12 "crypto/sha256"
13 "crypto/subtle"
14 "errors"
15 "io"
16
17 "golang.org/x/crypto/cryptobyte"
18 )
19
20
21
22 type sessionState struct {
23 vers uint16
24 cipherSuite uint16
25 createdAt uint64
26 masterSecret []byte
27
28 certificates [][]byte
29
30
31
32 usedOldKey bool
33 }
34
35 func (m *sessionState) marshal() []byte {
36 var b cryptobyte.Builder
37 b.AddUint16(m.vers)
38 b.AddUint16(m.cipherSuite)
39 addUint64(&b, m.createdAt)
40 b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
41 b.AddBytes(m.masterSecret)
42 })
43 b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) {
44 for _, cert := range m.certificates {
45 b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) {
46 b.AddBytes(cert)
47 })
48 }
49 })
50 return b.BytesOrPanic()
51 }
52
53 func (m *sessionState) unmarshal(data []byte) bool {
54 *m = sessionState{usedOldKey: m.usedOldKey}
55 s := cryptobyte.String(data)
56 if ok := s.ReadUint16(&m.vers) &&
57 s.ReadUint16(&m.cipherSuite) &&
58 readUint64(&s, &m.createdAt) &&
59 readUint16LengthPrefixed(&s, &m.masterSecret) &&
60 len(m.masterSecret) != 0; !ok {
61 return false
62 }
63 var certList cryptobyte.String
64 if !s.ReadUint24LengthPrefixed(&certList) {
65 return false
66 }
67 for !certList.Empty() {
68 var cert []byte
69 if !readUint24LengthPrefixed(&certList, &cert) {
70 return false
71 }
72 m.certificates = append(m.certificates, cert)
73 }
74 return s.Empty()
75 }
76
77
78
79
80 type sessionStateTLS13 struct {
81
82
83 cipherSuite uint16
84 createdAt uint64
85 resumptionSecret []byte
86 certificate Certificate
87 }
88
89 func (m *sessionStateTLS13) marshal() []byte {
90 var b cryptobyte.Builder
91 b.AddUint16(VersionTLS13)
92 b.AddUint8(0)
93 b.AddUint16(m.cipherSuite)
94 addUint64(&b, m.createdAt)
95 b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) {
96 b.AddBytes(m.resumptionSecret)
97 })
98 marshalCertificate(&b, m.certificate)
99 return b.BytesOrPanic()
100 }
101
102 func (m *sessionStateTLS13) unmarshal(data []byte) bool {
103 *m = sessionStateTLS13{}
104 s := cryptobyte.String(data)
105 var version uint16
106 var revision uint8
107 return s.ReadUint16(&version) &&
108 version == VersionTLS13 &&
109 s.ReadUint8(&revision) &&
110 revision == 0 &&
111 s.ReadUint16(&m.cipherSuite) &&
112 readUint64(&s, &m.createdAt) &&
113 readUint8LengthPrefixed(&s, &m.resumptionSecret) &&
114 len(m.resumptionSecret) != 0 &&
115 unmarshalCertificate(&s, &m.certificate) &&
116 s.Empty()
117 }
118
119 func (c *Conn) encryptTicket(state []byte) ([]byte, error) {
120 if len(c.ticketKeys) == 0 {
121 return nil, errors.New("tls: internal error: session ticket keys unavailable")
122 }
123
124 encrypted := make([]byte, ticketKeyNameLen+aes.BlockSize+len(state)+sha256.Size)
125 keyName := encrypted[:ticketKeyNameLen]
126 iv := encrypted[ticketKeyNameLen : ticketKeyNameLen+aes.BlockSize]
127 macBytes := encrypted[len(encrypted)-sha256.Size:]
128
129 if _, err := io.ReadFull(c.config.rand(), iv); err != nil {
130 return nil, err
131 }
132 key := c.ticketKeys[0]
133 copy(keyName, key.keyName[:])
134 block, err := aes.NewCipher(key.aesKey[:])
135 if err != nil {
136 return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error())
137 }
138 cipher.NewCTR(block, iv).XORKeyStream(encrypted[ticketKeyNameLen+aes.BlockSize:], state)
139
140 mac := hmac.New(sha256.New, key.hmacKey[:])
141 mac.Write(encrypted[:len(encrypted)-sha256.Size])
142 mac.Sum(macBytes[:0])
143
144 return encrypted, nil
145 }
146
147 func (c *Conn) decryptTicket(encrypted []byte) (plaintext []byte, usedOldKey bool) {
148 if len(encrypted) < ticketKeyNameLen+aes.BlockSize+sha256.Size {
149 return nil, false
150 }
151
152 keyName := encrypted[:ticketKeyNameLen]
153 iv := encrypted[ticketKeyNameLen : ticketKeyNameLen+aes.BlockSize]
154 macBytes := encrypted[len(encrypted)-sha256.Size:]
155 ciphertext := encrypted[ticketKeyNameLen+aes.BlockSize : len(encrypted)-sha256.Size]
156
157 keyIndex := -1
158 for i, candidateKey := range c.ticketKeys {
159 if bytes.Equal(keyName, candidateKey.keyName[:]) {
160 keyIndex = i
161 break
162 }
163 }
164 if keyIndex == -1 {
165 return nil, false
166 }
167 key := &c.ticketKeys[keyIndex]
168
169 mac := hmac.New(sha256.New, key.hmacKey[:])
170 mac.Write(encrypted[:len(encrypted)-sha256.Size])
171 expected := mac.Sum(nil)
172
173 if subtle.ConstantTimeCompare(macBytes, expected) != 1 {
174 return nil, false
175 }
176
177 block, err := aes.NewCipher(key.aesKey[:])
178 if err != nil {
179 return nil, false
180 }
181 plaintext = make([]byte, len(ciphertext))
182 cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext)
183
184 return plaintext, keyIndex > 0
185 }
186
View as plain text