gitee.com/lh-her-team/common@v1.5.1/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 "golang.org/x/crypto/cryptobyte" 18 ) 19 20 // sessionState contains the information that is serialized into a session 21 // ticket in order to later resume a connection. 22 type sessionState struct { 23 vers uint16 24 cipherSuite uint16 25 masterSecret []byte 26 certificates [][]byte 27 // usedOldKey is true if the ticket from which this session came from 28 // was encrypted with an older key and thus should be refreshed. 29 usedOldKey bool 30 } 31 32 func (s *sessionState) marshal() []byte { 33 length := 2 + 2 + 2 + len(s.masterSecret) + 2 34 for _, cert := range s.certificates { 35 length += 4 + len(cert) 36 } 37 ret := make([]byte, length) 38 x := ret 39 x[0] = byte(s.vers >> 8) 40 x[1] = byte(s.vers) 41 x[2] = byte(s.cipherSuite >> 8) 42 x[3] = byte(s.cipherSuite) 43 x[4] = byte(len(s.masterSecret) >> 8) 44 x[5] = byte(len(s.masterSecret)) 45 x = x[6:] 46 copy(x, s.masterSecret) 47 x = x[len(s.masterSecret):] 48 x[0] = byte(len(s.certificates) >> 8) 49 x[1] = byte(len(s.certificates)) 50 x = x[2:] 51 for _, cert := range s.certificates { 52 x[0] = byte(len(cert) >> 24) 53 x[1] = byte(len(cert) >> 16) 54 x[2] = byte(len(cert) >> 8) 55 x[3] = byte(len(cert)) 56 copy(x[4:], cert) 57 x = x[4+len(cert):] 58 } 59 return ret 60 } 61 62 func (s *sessionState) unmarshal(data []byte) bool { 63 if len(data) < 8 { 64 return false 65 } 66 s.vers = uint16(data[0])<<8 | uint16(data[1]) 67 s.cipherSuite = uint16(data[2])<<8 | uint16(data[3]) 68 masterSecretLen := int(data[4])<<8 | int(data[5]) 69 data = data[6:] 70 if len(data) < masterSecretLen { 71 return false 72 } 73 s.masterSecret = data[:masterSecretLen] 74 data = data[masterSecretLen:] 75 if len(data) < 2 { 76 return false 77 } 78 numCerts := int(data[0])<<8 | int(data[1]) 79 data = data[2:] 80 s.certificates = make([][]byte, numCerts) 81 for i := range s.certificates { 82 if len(data) < 4 { 83 return false 84 } 85 certLen := int(data[0])<<24 | int(data[1])<<16 | int(data[2])<<8 | int(data[3]) 86 data = data[4:] 87 if certLen < 0 { 88 return false 89 } 90 if len(data) < certLen { 91 return false 92 } 93 s.certificates[i] = data[:certLen] 94 data = data[certLen:] 95 } 96 return len(data) == 0 97 } 98 99 // sessionStateTLS13 is the content of a TLS 1.3 session ticket. Its first 100 // version (revision = 0) doesn't carry any of the information needed for 0-RTT 101 // validation and the nonce is always empty. 102 type sessionStateTLS13 struct { 103 // uint8 version = 0x0304; 104 // uint8 revision = 0; 105 cipherSuite uint16 106 createdAt uint64 107 resumptionSecret []byte // opaque resumption_master_secret<1..2^8-1>; 108 certificate Certificate // CertificateEntry certificate_list<0..2^24-1>; 109 } 110 111 func (m *sessionStateTLS13) marshal() []byte { 112 var b cryptobyte.Builder 113 b.AddUint16(VersionTLS13) 114 b.AddUint8(0) // revision 115 b.AddUint16(m.cipherSuite) 116 addUint64(&b, m.createdAt) 117 b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { 118 b.AddBytes(m.resumptionSecret) 119 }) 120 marshalCertificate(&b, m.certificate) 121 return b.BytesOrPanic() 122 } 123 124 func (m *sessionStateTLS13) unmarshal(data []byte) bool { 125 *m = sessionStateTLS13{} 126 s := cryptobyte.String(data) 127 var version uint16 128 var revision uint8 129 return s.ReadUint16(&version) && 130 version == VersionTLS13 && 131 s.ReadUint8(&revision) && 132 revision == 0 && 133 s.ReadUint16(&m.cipherSuite) && 134 readUint64(&s, &m.createdAt) && 135 readUint8LengthPrefixed(&s, &m.resumptionSecret) && 136 len(m.resumptionSecret) != 0 && 137 unmarshalCertificate(&s, &m.certificate) && 138 s.Empty() 139 } 140 141 func (c *Conn) encryptTicket(state []byte) ([]byte, error) { 142 encrypted := make([]byte, ticketKeyNameLen+aes.BlockSize+len(state)+sha256.Size) 143 keyName := encrypted[:ticketKeyNameLen] 144 iv := encrypted[ticketKeyNameLen : ticketKeyNameLen+aes.BlockSize] 145 macBytes := encrypted[len(encrypted)-sha256.Size:] 146 if _, err := io.ReadFull(c.config.rand(), iv); err != nil { 147 return nil, err 148 } 149 key := c.config.ticketKeys()[0] 150 copy(keyName, key.keyName[:]) 151 block, err := aes.NewCipher(key.aesKey[:]) 152 if err != nil { 153 return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error()) 154 } 155 cipher.NewCTR(block, iv).XORKeyStream(encrypted[ticketKeyNameLen+aes.BlockSize:], state) 156 mac := hmac.New(sha256.New, key.hmacKey[:]) 157 mac.Write(encrypted[:len(encrypted)-sha256.Size]) 158 mac.Sum(macBytes[:0]) 159 return encrypted, nil 160 } 161 162 func (c *Conn) decryptTicket(encrypted []byte) (plaintext []byte, usedOldKey bool) { 163 if len(encrypted) < ticketKeyNameLen+aes.BlockSize+sha256.Size { 164 return nil, false 165 } 166 keyName := encrypted[:ticketKeyNameLen] 167 iv := encrypted[ticketKeyNameLen : ticketKeyNameLen+aes.BlockSize] 168 macBytes := encrypted[len(encrypted)-sha256.Size:] 169 ciphertext := encrypted[ticketKeyNameLen+aes.BlockSize : len(encrypted)-sha256.Size] 170 keys := c.config.ticketKeys() 171 keyIndex := -1 172 for i, candidateKey := range keys { 173 if bytes.Equal(keyName, candidateKey.keyName[:]) { 174 keyIndex = i 175 break 176 } 177 } 178 if keyIndex == -1 { 179 return nil, false 180 } 181 key := &keys[keyIndex] 182 mac := hmac.New(sha256.New, key.hmacKey[:]) 183 mac.Write(encrypted[:len(encrypted)-sha256.Size]) 184 expected := mac.Sum(nil) 185 if subtle.ConstantTimeCompare(macBytes, expected) != 1 { 186 return nil, false 187 } 188 block, err := aes.NewCipher(key.aesKey[:]) 189 if err != nil { 190 return nil, false 191 } 192 plaintext = make([]byte, len(ciphertext)) 193 cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext) 194 return plaintext, keyIndex > 0 195 }