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