~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/Azure/azure-sdk-for-go/core/tls/ticket.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.
 
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
 
 
18
// sessionState contains the information that is serialized into a session
 
19
// ticket in order to later resume a connection.
 
20
type sessionState struct {
 
21
        vers         uint16
 
22
        cipherSuite  uint16
 
23
        masterSecret []byte
 
24
        certificates [][]byte
 
25
}
 
26
 
 
27
func (s *sessionState) equal(i interface{}) bool {
 
28
        s1, ok := i.(*sessionState)
 
29
        if !ok {
 
30
                return false
 
31
        }
 
32
 
 
33
        if s.vers != s1.vers ||
 
34
                s.cipherSuite != s1.cipherSuite ||
 
35
                !bytes.Equal(s.masterSecret, s1.masterSecret) {
 
36
                return false
 
37
        }
 
38
 
 
39
        if len(s.certificates) != len(s1.certificates) {
 
40
                return false
 
41
        }
 
42
 
 
43
        for i := range s.certificates {
 
44
                if !bytes.Equal(s.certificates[i], s1.certificates[i]) {
 
45
                        return false
 
46
                }
 
47
        }
 
48
 
 
49
        return true
 
50
}
 
51
 
 
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)
 
56
        }
 
57
 
 
58
        ret := make([]byte, length)
 
59
        x := ret
 
60
        x[0] = byte(s.vers >> 8)
 
61
        x[1] = byte(s.vers)
 
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))
 
66
        x = x[6:]
 
67
        copy(x, s.masterSecret)
 
68
        x = x[len(s.masterSecret):]
 
69
 
 
70
        x[0] = byte(len(s.certificates) >> 8)
 
71
        x[1] = byte(len(s.certificates))
 
72
        x = x[2:]
 
73
 
 
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))
 
79
                copy(x[4:], cert)
 
80
                x = x[4+len(cert):]
 
81
        }
 
82
 
 
83
        return ret
 
84
}
 
85
 
 
86
func (s *sessionState) unmarshal(data []byte) bool {
 
87
        if len(data) < 8 {
 
88
                return false
 
89
        }
 
90
 
 
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])
 
94
        data = data[6:]
 
95
        if len(data) < masterSecretLen {
 
96
                return false
 
97
        }
 
98
 
 
99
        s.masterSecret = data[:masterSecretLen]
 
100
        data = data[masterSecretLen:]
 
101
 
 
102
        if len(data) < 2 {
 
103
                return false
 
104
        }
 
105
 
 
106
        numCerts := int(data[0])<<8 | int(data[1])
 
107
        data = data[2:]
 
108
 
 
109
        s.certificates = make([][]byte, numCerts)
 
110
        for i := range s.certificates {
 
111
                if len(data) < 4 {
 
112
                        return false
 
113
                }
 
114
                certLen := int(data[0])<<24 | int(data[1])<<16 | int(data[2])<<8 | int(data[3])
 
115
                data = data[4:]
 
116
                if certLen < 0 {
 
117
                        return false
 
118
                }
 
119
                if len(data) < certLen {
 
120
                        return false
 
121
                }
 
122
                s.certificates[i] = data[:certLen]
 
123
                data = data[certLen:]
 
124
        }
 
125
 
 
126
        if len(data) > 0 {
 
127
                return false
 
128
        }
 
129
 
 
130
        return true
 
131
}
 
132
 
 
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:]
 
138
 
 
139
        if _, err := io.ReadFull(c.config.rand(), iv); err != nil {
 
140
                return nil, err
 
141
        }
 
142
        block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
 
143
        if err != nil {
 
144
                return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error())
 
145
        }
 
146
        cipher.NewCTR(block, iv).XORKeyStream(encrypted[aes.BlockSize:], serialized)
 
147
 
 
148
        mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
 
149
        mac.Write(encrypted[:len(encrypted)-sha256.Size])
 
150
        mac.Sum(macBytes[:0])
 
151
 
 
152
        return encrypted, nil
 
153
}
 
154
 
 
155
func (c *Conn) decryptTicket(encrypted []byte) (*sessionState, bool) {
 
156
        if len(encrypted) < aes.BlockSize+sha256.Size {
 
157
                return nil, false
 
158
        }
 
159
 
 
160
        iv := encrypted[:aes.BlockSize]
 
161
        macBytes := encrypted[len(encrypted)-sha256.Size:]
 
162
 
 
163
        mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32])
 
164
        mac.Write(encrypted[:len(encrypted)-sha256.Size])
 
165
        expected := mac.Sum(nil)
 
166
 
 
167
        if subtle.ConstantTimeCompare(macBytes, expected) != 1 {
 
168
                return nil, false
 
169
        }
 
170
 
 
171
        block, err := aes.NewCipher(c.config.SessionTicketKey[:16])
 
172
        if err != nil {
 
173
                return nil, false
 
174
        }
 
175
        ciphertext := encrypted[aes.BlockSize : len(encrypted)-sha256.Size]
 
176
        plaintext := ciphertext
 
177
        cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext)
 
178
 
 
179
        state := new(sessionState)
 
180
        ok := state.unmarshal(plaintext)
 
181
        return state, ok
 
182
}