github.com/3andne/restls-client-go@v0.1.6/u_public.go (about)

     1  // Copyright 2017 Google Inc. 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  	"crypto"
     9  	"crypto/ecdh"
    10  	"crypto/x509"
    11  	"hash"
    12  	"time"
    13  )
    14  
    15  // ClientHandshakeState includes both TLS 1.3-only and TLS 1.2-only states,
    16  // only one of them will be used, depending on negotiated version.
    17  //
    18  // ClientHandshakeState will be converted into and from either
    19  //   - clientHandshakeState      (TLS 1.2)
    20  //   - clientHandshakeStateTLS13 (TLS 1.3)
    21  //
    22  // uTLS will call .handshake() on one of these private internal states,
    23  // to perform TLS handshake using standard crypto/tls implementation.
    24  type PubClientHandshakeState struct {
    25  	C            *Conn
    26  	ServerHello  *PubServerHelloMsg
    27  	Hello        *PubClientHelloMsg
    28  	MasterSecret []byte
    29  	Session      *SessionState
    30  
    31  	State12 TLS12OnlyState
    32  	State13 TLS13OnlyState
    33  
    34  	uconn *UConn
    35  }
    36  
    37  // TLS 1.3 only
    38  type TLS13OnlyState struct {
    39  	Suite                *PubCipherSuiteTLS13
    40  	EcdheKey             *ecdh.PrivateKey
    41  	KeySharesEcdheParams KeySharesEcdheParameters
    42  	EarlySecret          []byte
    43  	BinderKey            []byte
    44  	CertReq              *CertificateRequestMsgTLS13
    45  	UsingPSK             bool
    46  	SentDummyCCS         bool
    47  	Transcript           hash.Hash
    48  	TrafficSecret        []byte // client_application_traffic_secret_0
    49  }
    50  
    51  // TLS 1.2 and before only
    52  type TLS12OnlyState struct {
    53  	FinishedHash FinishedHash
    54  	Suite        PubCipherSuite
    55  }
    56  
    57  func (chs *PubClientHandshakeState) toPrivate13() *clientHandshakeStateTLS13 {
    58  	if chs == nil {
    59  		return nil
    60  	} else {
    61  		return &clientHandshakeStateTLS13{
    62  			c:                    chs.C,
    63  			serverHello:          chs.ServerHello.getPrivatePtr(),
    64  			hello:                chs.Hello.getPrivatePtr(),
    65  			ecdheKey:             chs.State13.EcdheKey,
    66  			keySharesEcdheParams: chs.State13.KeySharesEcdheParams,
    67  
    68  			session:     chs.Session,
    69  			earlySecret: chs.State13.EarlySecret,
    70  			binderKey:   chs.State13.BinderKey,
    71  
    72  			certReq:       chs.State13.CertReq.toPrivate(),
    73  			usingPSK:      chs.State13.UsingPSK,
    74  			sentDummyCCS:  chs.State13.SentDummyCCS,
    75  			suite:         chs.State13.Suite.toPrivate(),
    76  			transcript:    chs.State13.Transcript,
    77  			masterSecret:  chs.MasterSecret,
    78  			trafficSecret: chs.State13.TrafficSecret,
    79  
    80  			uconn: chs.uconn,
    81  		}
    82  	}
    83  }
    84  
    85  func (chs13 *clientHandshakeStateTLS13) toPublic13() *PubClientHandshakeState {
    86  	if chs13 == nil {
    87  		return nil
    88  	} else {
    89  		tls13State := TLS13OnlyState{
    90  			KeySharesEcdheParams: chs13.keySharesEcdheParams,
    91  			EcdheKey:             chs13.ecdheKey,
    92  			EarlySecret:          chs13.earlySecret,
    93  			BinderKey:            chs13.binderKey,
    94  			CertReq:              chs13.certReq.toPublic(),
    95  			UsingPSK:             chs13.usingPSK,
    96  			SentDummyCCS:         chs13.sentDummyCCS,
    97  			Suite:                chs13.suite.toPublic(),
    98  			TrafficSecret:        chs13.trafficSecret,
    99  			Transcript:           chs13.transcript,
   100  		}
   101  		return &PubClientHandshakeState{
   102  			C:           chs13.c,
   103  			ServerHello: chs13.serverHello.getPublicPtr(),
   104  			Hello:       chs13.hello.getPublicPtr(),
   105  
   106  			Session: chs13.session,
   107  
   108  			MasterSecret: chs13.masterSecret,
   109  
   110  			State13: tls13State,
   111  
   112  			uconn: chs13.uconn,
   113  		}
   114  	}
   115  }
   116  
   117  func (chs *PubClientHandshakeState) toPrivate12() *clientHandshakeState {
   118  	if chs == nil {
   119  		return nil
   120  	} else {
   121  		return &clientHandshakeState{
   122  			c:           chs.C,
   123  			serverHello: chs.ServerHello.getPrivatePtr(),
   124  			hello:       chs.Hello.getPrivatePtr(),
   125  			suite:       chs.State12.Suite.getPrivatePtr(),
   126  			session:     chs.Session,
   127  
   128  			masterSecret: chs.MasterSecret,
   129  
   130  			finishedHash: chs.State12.FinishedHash.getPrivateObj(),
   131  
   132  			uconn: chs.uconn,
   133  		}
   134  	}
   135  }
   136  
   137  func (chs12 *clientHandshakeState) toPublic12() *PubClientHandshakeState {
   138  	if chs12 == nil {
   139  		return nil
   140  	} else {
   141  		tls12State := TLS12OnlyState{
   142  			Suite:        chs12.suite.getPublicObj(),
   143  			FinishedHash: chs12.finishedHash.getPublicObj(),
   144  		}
   145  		return &PubClientHandshakeState{
   146  			C:           chs12.c,
   147  			ServerHello: chs12.serverHello.getPublicPtr(),
   148  			Hello:       chs12.hello.getPublicPtr(),
   149  
   150  			Session: chs12.session,
   151  
   152  			MasterSecret: chs12.masterSecret,
   153  
   154  			State12: tls12State,
   155  
   156  			uconn: chs12.uconn,
   157  		}
   158  	}
   159  }
   160  
   161  // type EcdheParameters interface {
   162  // 	ecdheParameters
   163  // }
   164  
   165  type CertificateRequestMsgTLS13 struct {
   166  	Raw                              []byte
   167  	OcspStapling                     bool
   168  	Scts                             bool
   169  	SupportedSignatureAlgorithms     []SignatureScheme
   170  	SupportedSignatureAlgorithmsCert []SignatureScheme
   171  	CertificateAuthorities           [][]byte
   172  }
   173  
   174  func (crm *certificateRequestMsgTLS13) toPublic() *CertificateRequestMsgTLS13 {
   175  	if crm == nil {
   176  		return nil
   177  	} else {
   178  		return &CertificateRequestMsgTLS13{
   179  			Raw:                              crm.raw,
   180  			OcspStapling:                     crm.ocspStapling,
   181  			Scts:                             crm.scts,
   182  			SupportedSignatureAlgorithms:     crm.supportedSignatureAlgorithms,
   183  			SupportedSignatureAlgorithmsCert: crm.supportedSignatureAlgorithmsCert,
   184  			CertificateAuthorities:           crm.certificateAuthorities,
   185  		}
   186  	}
   187  }
   188  
   189  func (crm *CertificateRequestMsgTLS13) toPrivate() *certificateRequestMsgTLS13 {
   190  	if crm == nil {
   191  		return nil
   192  	} else {
   193  		return &certificateRequestMsgTLS13{
   194  			raw:                              crm.Raw,
   195  			ocspStapling:                     crm.OcspStapling,
   196  			scts:                             crm.Scts,
   197  			supportedSignatureAlgorithms:     crm.SupportedSignatureAlgorithms,
   198  			supportedSignatureAlgorithmsCert: crm.SupportedSignatureAlgorithmsCert,
   199  			certificateAuthorities:           crm.CertificateAuthorities,
   200  		}
   201  	}
   202  }
   203  
   204  type PubCipherSuiteTLS13 struct {
   205  	Id     uint16
   206  	KeyLen int
   207  	Aead   func(key, fixedNonce []byte) aead
   208  	Hash   crypto.Hash
   209  }
   210  
   211  func (c *cipherSuiteTLS13) toPublic() *PubCipherSuiteTLS13 {
   212  	if c == nil {
   213  		return nil
   214  	} else {
   215  		return &PubCipherSuiteTLS13{
   216  			Id:     c.id,
   217  			KeyLen: c.keyLen,
   218  			Aead:   c.aead,
   219  			Hash:   c.hash,
   220  		}
   221  	}
   222  }
   223  
   224  func (c *PubCipherSuiteTLS13) toPrivate() *cipherSuiteTLS13 {
   225  	if c == nil {
   226  		return nil
   227  	} else {
   228  		return &cipherSuiteTLS13{
   229  			id:     c.Id,
   230  			keyLen: c.KeyLen,
   231  			aead:   c.Aead,
   232  			hash:   c.Hash,
   233  		}
   234  	}
   235  }
   236  
   237  type PubServerHelloMsg struct {
   238  	Raw                          []byte
   239  	Vers                         uint16
   240  	Random                       []byte
   241  	SessionId                    []byte
   242  	CipherSuite                  uint16
   243  	CompressionMethod            uint8
   244  	NextProtoNeg                 bool
   245  	NextProtos                   []string
   246  	OcspStapling                 bool
   247  	Scts                         [][]byte
   248  	ExtendedMasterSecret         bool
   249  	TicketSupported              bool
   250  	SecureRenegotiation          []byte
   251  	SecureRenegotiationSupported bool
   252  	AlpnProtocol                 string
   253  
   254  	// 1.3
   255  	SupportedVersion        uint16
   256  	ServerShare             keyShare
   257  	SelectedIdentityPresent bool
   258  	SelectedIdentity        uint16
   259  	Cookie                  []byte  // HelloRetryRequest extension
   260  	SelectedGroup           CurveID // HelloRetryRequest extension
   261  
   262  }
   263  
   264  func (shm *PubServerHelloMsg) getPrivatePtr() *serverHelloMsg {
   265  	if shm == nil {
   266  		return nil
   267  	} else {
   268  		return &serverHelloMsg{
   269  			raw:                          shm.Raw,
   270  			vers:                         shm.Vers,
   271  			random:                       shm.Random,
   272  			sessionId:                    shm.SessionId,
   273  			cipherSuite:                  shm.CipherSuite,
   274  			compressionMethod:            shm.CompressionMethod,
   275  			nextProtoNeg:                 shm.NextProtoNeg,
   276  			nextProtos:                   shm.NextProtos,
   277  			ocspStapling:                 shm.OcspStapling,
   278  			scts:                         shm.Scts,
   279  			extendedMasterSecret:         shm.ExtendedMasterSecret,
   280  			ticketSupported:              shm.TicketSupported,
   281  			secureRenegotiation:          shm.SecureRenegotiation,
   282  			secureRenegotiationSupported: shm.SecureRenegotiationSupported,
   283  			alpnProtocol:                 shm.AlpnProtocol,
   284  			supportedVersion:             shm.SupportedVersion,
   285  			serverShare:                  shm.ServerShare,
   286  			selectedIdentityPresent:      shm.SelectedIdentityPresent,
   287  			selectedIdentity:             shm.SelectedIdentity,
   288  			cookie:                       shm.Cookie,
   289  			selectedGroup:                shm.SelectedGroup,
   290  		}
   291  	}
   292  }
   293  
   294  func (shm *serverHelloMsg) getPublicPtr() *PubServerHelloMsg {
   295  	if shm == nil {
   296  		return nil
   297  	} else {
   298  		return &PubServerHelloMsg{
   299  			Raw:                          shm.raw,
   300  			Vers:                         shm.vers,
   301  			Random:                       shm.random,
   302  			SessionId:                    shm.sessionId,
   303  			CipherSuite:                  shm.cipherSuite,
   304  			CompressionMethod:            shm.compressionMethod,
   305  			NextProtoNeg:                 shm.nextProtoNeg,
   306  			NextProtos:                   shm.nextProtos,
   307  			OcspStapling:                 shm.ocspStapling,
   308  			Scts:                         shm.scts,
   309  			ExtendedMasterSecret:         shm.extendedMasterSecret,
   310  			TicketSupported:              shm.ticketSupported,
   311  			SecureRenegotiation:          shm.secureRenegotiation,
   312  			SecureRenegotiationSupported: shm.secureRenegotiationSupported,
   313  			AlpnProtocol:                 shm.alpnProtocol,
   314  			SupportedVersion:             shm.supportedVersion,
   315  			ServerShare:                  shm.serverShare,
   316  			SelectedIdentityPresent:      shm.selectedIdentityPresent,
   317  			SelectedIdentity:             shm.selectedIdentity,
   318  			Cookie:                       shm.cookie,
   319  			SelectedGroup:                shm.selectedGroup,
   320  		}
   321  	}
   322  }
   323  
   324  type PubClientHelloMsg struct {
   325  	Raw                          []byte
   326  	Vers                         uint16
   327  	Random                       []byte
   328  	SessionId                    []byte
   329  	CipherSuites                 []uint16
   330  	CompressionMethods           []uint8
   331  	NextProtoNeg                 bool
   332  	ServerName                   string
   333  	OcspStapling                 bool
   334  	Scts                         bool
   335  	Ems                          bool // [uTLS] actually implemented due to its prevalence
   336  	SupportedCurves              []CurveID
   337  	SupportedPoints              []uint8
   338  	TicketSupported              bool
   339  	SessionTicket                []uint8
   340  	SupportedSignatureAlgorithms []SignatureScheme
   341  	SecureRenegotiation          []byte
   342  	SecureRenegotiationSupported bool
   343  	AlpnProtocols                []string
   344  
   345  	// 1.3
   346  	SupportedSignatureAlgorithmsCert []SignatureScheme
   347  	SupportedVersions                []uint16
   348  	Cookie                           []byte
   349  	KeyShares                        []KeyShare
   350  	EarlyData                        bool
   351  	PskModes                         []uint8
   352  	PskIdentities                    []PskIdentity
   353  	PskBinders                       [][]byte
   354  	QuicTransportParameters          []byte
   355  }
   356  
   357  func (chm *PubClientHelloMsg) getPrivatePtr() *clientHelloMsg {
   358  	if chm == nil {
   359  		return nil
   360  	} else {
   361  		return &clientHelloMsg{
   362  			raw:                              chm.Raw,
   363  			vers:                             chm.Vers,
   364  			random:                           chm.Random,
   365  			sessionId:                        chm.SessionId,
   366  			cipherSuites:                     chm.CipherSuites,
   367  			compressionMethods:               chm.CompressionMethods,
   368  			serverName:                       chm.ServerName,
   369  			ocspStapling:                     chm.OcspStapling,
   370  			supportedCurves:                  chm.SupportedCurves,
   371  			supportedPoints:                  chm.SupportedPoints,
   372  			ticketSupported:                  chm.TicketSupported,
   373  			sessionTicket:                    chm.SessionTicket,
   374  			supportedSignatureAlgorithms:     chm.SupportedSignatureAlgorithms,
   375  			supportedSignatureAlgorithmsCert: chm.SupportedSignatureAlgorithmsCert,
   376  			secureRenegotiationSupported:     chm.SecureRenegotiationSupported,
   377  			secureRenegotiation:              chm.SecureRenegotiation,
   378  			extendedMasterSecret:             chm.Ems,
   379  			alpnProtocols:                    chm.AlpnProtocols,
   380  			scts:                             chm.Scts,
   381  
   382  			supportedVersions:       chm.SupportedVersions,
   383  			cookie:                  chm.Cookie,
   384  			keyShares:               KeyShares(chm.KeyShares).ToPrivate(),
   385  			earlyData:               chm.EarlyData,
   386  			pskModes:                chm.PskModes,
   387  			pskIdentities:           PskIdentities(chm.PskIdentities).ToPrivate(),
   388  			pskBinders:              chm.PskBinders,
   389  			quicTransportParameters: chm.QuicTransportParameters,
   390  
   391  			nextProtoNeg: chm.NextProtoNeg,
   392  		}
   393  	}
   394  }
   395  
   396  func (chm *clientHelloMsg) getPublicPtr() *PubClientHelloMsg {
   397  	if chm == nil {
   398  		return nil
   399  	} else {
   400  		return &PubClientHelloMsg{
   401  			Raw:                          chm.raw,
   402  			Vers:                         chm.vers,
   403  			Random:                       chm.random,
   404  			SessionId:                    chm.sessionId,
   405  			CipherSuites:                 chm.cipherSuites,
   406  			CompressionMethods:           chm.compressionMethods,
   407  			NextProtoNeg:                 chm.nextProtoNeg,
   408  			ServerName:                   chm.serverName,
   409  			OcspStapling:                 chm.ocspStapling,
   410  			Scts:                         chm.scts,
   411  			Ems:                          chm.extendedMasterSecret,
   412  			SupportedCurves:              chm.supportedCurves,
   413  			SupportedPoints:              chm.supportedPoints,
   414  			TicketSupported:              chm.ticketSupported,
   415  			SessionTicket:                chm.sessionTicket,
   416  			SupportedSignatureAlgorithms: chm.supportedSignatureAlgorithms,
   417  			SecureRenegotiation:          chm.secureRenegotiation,
   418  			SecureRenegotiationSupported: chm.secureRenegotiationSupported,
   419  			AlpnProtocols:                chm.alpnProtocols,
   420  
   421  			SupportedSignatureAlgorithmsCert: chm.supportedSignatureAlgorithmsCert,
   422  			SupportedVersions:                chm.supportedVersions,
   423  			Cookie:                           chm.cookie,
   424  			KeyShares:                        keyShares(chm.keyShares).ToPublic(),
   425  			EarlyData:                        chm.earlyData,
   426  			PskModes:                         chm.pskModes,
   427  			PskIdentities:                    pskIdentities(chm.pskIdentities).ToPublic(),
   428  			PskBinders:                       chm.pskBinders,
   429  			QuicTransportParameters:          chm.quicTransportParameters,
   430  		}
   431  	}
   432  }
   433  
   434  // UnmarshalClientHello allows external code to parse raw client hellos.
   435  // It returns nil on failure.
   436  func UnmarshalClientHello(data []byte) *PubClientHelloMsg {
   437  	m := &clientHelloMsg{}
   438  	if m.unmarshal(data) {
   439  		return m.getPublicPtr()
   440  	}
   441  	return nil
   442  }
   443  
   444  // Marshal allows external code to convert a ClientHello object back into
   445  // raw bytes.
   446  func (chm *PubClientHelloMsg) Marshal() ([]byte, error) {
   447  	return chm.getPrivatePtr().marshal()
   448  }
   449  
   450  // A CipherSuite is a specific combination of key agreement, cipher and MAC
   451  // function. All cipher suites currently assume RSA key agreement.
   452  type PubCipherSuite struct {
   453  	Id uint16
   454  	// the lengths, in bytes, of the key material needed for each component.
   455  	KeyLen int
   456  	MacLen int
   457  	IvLen  int
   458  	Ka     func(version uint16) keyAgreement
   459  	// flags is a bitmask of the suite* values, above.
   460  	Flags  int
   461  	Cipher func(key, iv []byte, isRead bool) interface{}
   462  	Mac    func(macKey []byte) hash.Hash
   463  	Aead   func(key, fixedNonce []byte) aead
   464  }
   465  
   466  func (cs *PubCipherSuite) getPrivatePtr() *cipherSuite {
   467  	if cs == nil {
   468  		return nil
   469  	} else {
   470  		return &cipherSuite{
   471  			id:     cs.Id,
   472  			keyLen: cs.KeyLen,
   473  			macLen: cs.MacLen,
   474  			ivLen:  cs.IvLen,
   475  			ka:     cs.Ka,
   476  			flags:  cs.Flags,
   477  			cipher: cs.Cipher,
   478  			mac:    cs.Mac,
   479  			aead:   cs.Aead,
   480  		}
   481  	}
   482  }
   483  
   484  func (cs *cipherSuite) getPublicObj() PubCipherSuite {
   485  	if cs == nil {
   486  		return PubCipherSuite{}
   487  	} else {
   488  		return PubCipherSuite{
   489  			Id:     cs.id,
   490  			KeyLen: cs.keyLen,
   491  			MacLen: cs.macLen,
   492  			IvLen:  cs.ivLen,
   493  			Ka:     cs.ka,
   494  			Flags:  cs.flags,
   495  			Cipher: cs.cipher,
   496  			Mac:    cs.mac,
   497  			Aead:   cs.aead,
   498  		}
   499  	}
   500  }
   501  
   502  // A FinishedHash calculates the hash of a set of handshake messages suitable
   503  // for including in a Finished message.
   504  type FinishedHash struct {
   505  	Client hash.Hash
   506  	Server hash.Hash
   507  
   508  	// Prior to TLS 1.2, an additional MD5 hash is required.
   509  	ClientMD5 hash.Hash
   510  	ServerMD5 hash.Hash
   511  
   512  	// In TLS 1.2, a full buffer is sadly required.
   513  	Buffer []byte
   514  
   515  	Version uint16
   516  	Prf     func(result, secret, label, seed []byte)
   517  }
   518  
   519  func (fh *FinishedHash) getPrivateObj() finishedHash {
   520  	if fh == nil {
   521  		return finishedHash{}
   522  	} else {
   523  		return finishedHash{
   524  			client:    fh.Client,
   525  			server:    fh.Server,
   526  			clientMD5: fh.ClientMD5,
   527  			serverMD5: fh.ServerMD5,
   528  			buffer:    fh.Buffer,
   529  			version:   fh.Version,
   530  			prf:       fh.Prf,
   531  		}
   532  	}
   533  }
   534  
   535  func (fh *finishedHash) getPublicObj() FinishedHash {
   536  	if fh == nil {
   537  		return FinishedHash{}
   538  	} else {
   539  		return FinishedHash{
   540  			Client:    fh.client,
   541  			Server:    fh.server,
   542  			ClientMD5: fh.clientMD5,
   543  			ServerMD5: fh.serverMD5,
   544  			Buffer:    fh.buffer,
   545  			Version:   fh.version,
   546  			Prf:       fh.prf}
   547  	}
   548  }
   549  
   550  // TLS 1.3 Key Share. See RFC 8446, Section 4.2.8.
   551  type KeyShare struct {
   552  	Group CurveID `json:"group"`
   553  	Data  []byte  `json:"key_exchange,omitempty"` // optional
   554  }
   555  
   556  type KeyShares []KeyShare
   557  type keyShares []keyShare
   558  
   559  func (kss keyShares) ToPublic() []KeyShare {
   560  	var KSS []KeyShare
   561  	for _, ks := range kss {
   562  		KSS = append(KSS, KeyShare{Data: ks.data, Group: ks.group})
   563  	}
   564  	return KSS
   565  }
   566  func (KSS KeyShares) ToPrivate() []keyShare {
   567  	var kss []keyShare
   568  	for _, KS := range KSS {
   569  		kss = append(kss, keyShare{data: KS.Data, group: KS.Group})
   570  	}
   571  	return kss
   572  }
   573  
   574  // TLS 1.3 PSK Identity. Can be a Session Ticket, or a reference to a saved
   575  // session. See RFC 8446, Section 4.2.11.
   576  type PskIdentity struct {
   577  	Label               []byte `json:"identity"`
   578  	ObfuscatedTicketAge uint32 `json:"obfuscated_ticket_age"`
   579  }
   580  
   581  type PskIdentities []PskIdentity
   582  type pskIdentities []pskIdentity
   583  
   584  func (pss pskIdentities) ToPublic() []PskIdentity {
   585  	var PSS []PskIdentity
   586  	for _, ps := range pss {
   587  		PSS = append(PSS, PskIdentity{Label: ps.label, ObfuscatedTicketAge: ps.obfuscatedTicketAge})
   588  	}
   589  	return PSS
   590  }
   591  
   592  func (PSS PskIdentities) ToPrivate() []pskIdentity {
   593  	var pss []pskIdentity
   594  	for _, PS := range PSS {
   595  		pss = append(pss, pskIdentity{label: PS.Label, obfuscatedTicketAge: PS.ObfuscatedTicketAge})
   596  	}
   597  	return pss
   598  }
   599  
   600  // ClientSessionState is public, but all its fields are private. Let's add setters, getters and constructor
   601  
   602  // ClientSessionState contains the state needed by clients to resume TLS sessions.
   603  func MakeClientSessionState(
   604  	SessionTicket []uint8,
   605  	Vers uint16,
   606  	CipherSuite uint16,
   607  	MasterSecret []byte,
   608  	ServerCertificates []*x509.Certificate,
   609  	VerifiedChains [][]*x509.Certificate) *ClientSessionState {
   610  	css := &ClientSessionState{
   611  		ticket: SessionTicket,
   612  		session: &SessionState{
   613  			version:          Vers,
   614  			cipherSuite:      CipherSuite,
   615  			secret:           MasterSecret,
   616  			peerCertificates: ServerCertificates,
   617  			verifiedChains:   VerifiedChains,
   618  		},
   619  	}
   620  	return css
   621  }
   622  
   623  // Encrypted ticket used for session resumption with server
   624  func (css *ClientSessionState) SessionTicket() []uint8 {
   625  	return css.ticket
   626  }
   627  
   628  // SSL/TLS version negotiated for the session
   629  func (css *ClientSessionState) Vers() uint16 {
   630  	return css.session.version
   631  }
   632  
   633  // Ciphersuite negotiated for the session
   634  func (css *ClientSessionState) CipherSuite() uint16 {
   635  	return css.session.cipherSuite
   636  }
   637  
   638  // MasterSecret generated by client on a full handshake
   639  func (css *ClientSessionState) MasterSecret() []byte {
   640  	return css.session.secret
   641  }
   642  
   643  // Certificate chain presented by the server
   644  func (css *ClientSessionState) ServerCertificates() []*x509.Certificate {
   645  	return css.session.peerCertificates
   646  }
   647  
   648  // Certificate chains we built for verification
   649  func (css *ClientSessionState) VerifiedChains() [][]*x509.Certificate {
   650  	return css.session.verifiedChains
   651  }
   652  
   653  func (css *ClientSessionState) SetSessionTicket(SessionTicket []uint8) {
   654  	css.ticket = SessionTicket
   655  }
   656  func (css *ClientSessionState) SetVers(Vers uint16) {
   657  	if css.session == nil {
   658  		css.session = &SessionState{}
   659  	}
   660  	css.session.version = Vers
   661  }
   662  func (css *ClientSessionState) SetCipherSuite(CipherSuite uint16) {
   663  	if css.session == nil {
   664  		css.session = &SessionState{}
   665  	}
   666  	css.session.cipherSuite = CipherSuite
   667  }
   668  func (css *ClientSessionState) SetMasterSecret(MasterSecret []byte) {
   669  	if css.session == nil {
   670  		css.session = &SessionState{}
   671  	}
   672  	css.session.secret = MasterSecret
   673  }
   674  func (css *ClientSessionState) SetServerCertificates(ServerCertificates []*x509.Certificate) {
   675  	if css.session == nil {
   676  		css.session = &SessionState{}
   677  	}
   678  	css.session.peerCertificates = ServerCertificates
   679  }
   680  func (css *ClientSessionState) SetVerifiedChains(VerifiedChains [][]*x509.Certificate) {
   681  	if css.session == nil {
   682  		css.session = &SessionState{}
   683  	}
   684  	css.session.verifiedChains = VerifiedChains
   685  }
   686  
   687  // TicketKey is the internal representation of a session ticket key.
   688  type TicketKey struct {
   689  	AesKey  [16]byte
   690  	HmacKey [16]byte
   691  	// created is the time at which this ticket key was created. See Config.ticketKeys.
   692  	Created time.Time
   693  }
   694  
   695  type TicketKeys []TicketKey
   696  type ticketKeys []ticketKey
   697  
   698  func TicketKeyFromBytes(b [32]byte) TicketKey {
   699  	// [uTLS]
   700  	// empty config is required
   701  	config := &Config{}
   702  	tk := config.ticketKeyFromBytes(b)
   703  	return tk.ToPublic()
   704  }
   705  
   706  func (tk ticketKey) ToPublic() TicketKey {
   707  	return TicketKey{
   708  		AesKey:  tk.aesKey,
   709  		HmacKey: tk.hmacKey,
   710  		Created: tk.created,
   711  	}
   712  }
   713  
   714  func (TK TicketKey) ToPrivate() ticketKey {
   715  	return ticketKey{
   716  		aesKey:  TK.AesKey,
   717  		hmacKey: TK.HmacKey,
   718  		created: TK.Created,
   719  	}
   720  }
   721  
   722  func (tks ticketKeys) ToPublic() []TicketKey {
   723  	var TKS []TicketKey
   724  	for _, ks := range tks {
   725  		TKS = append(TKS, ks.ToPublic())
   726  	}
   727  	return TKS
   728  }
   729  
   730  func (TKS TicketKeys) ToPrivate() []ticketKey {
   731  	var tks []ticketKey
   732  	for _, TK := range TKS {
   733  		tks = append(tks, TK.ToPrivate())
   734  	}
   735  	return tks
   736  }