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  }