github.com/roboticscm/goman@v0.0.0-20210203095141-87c07b4a0a55/src/crypto/tls/ticket.go (about) 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 c.config.SessionTicketsDisabled || 157 len(encrypted) < aes.BlockSize+sha256.Size { 158 return nil, false 159 } 160 161 iv := encrypted[:aes.BlockSize] 162 macBytes := encrypted[len(encrypted)-sha256.Size:] 163 164 mac := hmac.New(sha256.New, c.config.SessionTicketKey[16:32]) 165 mac.Write(encrypted[:len(encrypted)-sha256.Size]) 166 expected := mac.Sum(nil) 167 168 if subtle.ConstantTimeCompare(macBytes, expected) != 1 { 169 return nil, false 170 } 171 172 block, err := aes.NewCipher(c.config.SessionTicketKey[:16]) 173 if err != nil { 174 return nil, false 175 } 176 ciphertext := encrypted[aes.BlockSize : len(encrypted)-sha256.Size] 177 plaintext := ciphertext 178 cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext) 179 180 state := new(sessionState) 181 ok := state.unmarshal(plaintext) 182 return state, ok 183 }