mirror of
https://github.com/XTLS/REALITY.git
synced 2025-08-22 14:38:35 +00:00
crypto/tls: implement Extended Master Secret
All OpenSSL tests now test operation with EMS. To test a handshake *without* EMS we need to pass -Options=-ExtendedMasterSecret which is only available in OpenSSL 3.1, which breaks a number of other tests. Updates #43922 Change-Id: Ib9ac79a1d03fab6bfba5fe9cd66689cff661cda7 Reviewed-on: https://go-review.googlesource.com/c/go/+/497376 Run-TryBot: Filippo Valsorda <filippo@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Roland Shoemaker <roland@golang.org> Auto-Submit: Filippo Valsorda <filippo@golang.org> Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
parent
aa68126eeb
commit
14202975e0
13
common.go
13
common.go
@ -90,6 +90,7 @@ const (
|
|||||||
extensionSignatureAlgorithms uint16 = 13
|
extensionSignatureAlgorithms uint16 = 13
|
||||||
extensionALPN uint16 = 16
|
extensionALPN uint16 = 16
|
||||||
extensionSCT uint16 = 18
|
extensionSCT uint16 = 18
|
||||||
|
extensionExtendedMasterSecret uint16 = 23
|
||||||
extensionSessionTicket uint16 = 35
|
extensionSessionTicket uint16 = 35
|
||||||
extensionPreSharedKey uint16 = 41
|
extensionPreSharedKey uint16 = 41
|
||||||
extensionEarlyData uint16 = 42
|
extensionEarlyData uint16 = 42
|
||||||
@ -271,12 +272,8 @@ type ConnectionState struct {
|
|||||||
OCSPResponse []byte
|
OCSPResponse []byte
|
||||||
|
|
||||||
// TLSUnique contains the "tls-unique" channel binding value (see RFC 5929,
|
// TLSUnique contains the "tls-unique" channel binding value (see RFC 5929,
|
||||||
// Section 3). This value will be nil for TLS 1.3 connections and for all
|
// Section 3). This value will be nil for TLS 1.3 connections and for
|
||||||
// resumed connections.
|
// resumed connections that don't support Extended Master Secret (RFC 7627).
|
||||||
//
|
|
||||||
// Deprecated: there are conditions in which this value might not be unique
|
|
||||||
// to a connection. See the Security Considerations sections of RFC 5705 and
|
|
||||||
// RFC 7627, and https://mitls.org/pages/attacks/3SHAKE#channelbindings.
|
|
||||||
TLSUnique []byte
|
TLSUnique []byte
|
||||||
|
|
||||||
// ekm is a closure exposed via ExportKeyingMaterial.
|
// ekm is a closure exposed via ExportKeyingMaterial.
|
||||||
@ -287,6 +284,10 @@ type ConnectionState struct {
|
|||||||
// slice as defined in RFC 5705. If context is nil, it is not used as part of
|
// slice as defined in RFC 5705. If context is nil, it is not used as part of
|
||||||
// the seed. If the connection was set to allow renegotiation via
|
// the seed. If the connection was set to allow renegotiation via
|
||||||
// Config.Renegotiation, this function will return an error.
|
// Config.Renegotiation, this function will return an error.
|
||||||
|
//
|
||||||
|
// There are conditions in which the returned values might not be unique to a
|
||||||
|
// connection. See the Security Considerations sections of RFC 5705 and RFC 7627,
|
||||||
|
// and https://mitls.org/pages/attacks/3SHAKE#channelbindings.
|
||||||
func (cs *ConnectionState) ExportKeyingMaterial(label string, context []byte, length int) ([]byte, error) {
|
func (cs *ConnectionState) ExportKeyingMaterial(label string, context []byte, length int) ([]byte, error) {
|
||||||
return cs.ekm(label, context, length)
|
return cs.ekm(label, context, length)
|
||||||
}
|
}
|
||||||
|
3
conn.go
3
conn.go
@ -50,6 +50,7 @@ type Conn struct {
|
|||||||
// connection so far. If renegotiation is disabled then this is either
|
// connection so far. If renegotiation is disabled then this is either
|
||||||
// zero or one.
|
// zero or one.
|
||||||
handshakes int
|
handshakes int
|
||||||
|
extMasterSecret bool
|
||||||
didResume bool // whether this connection was a session resumption
|
didResume bool // whether this connection was a session resumption
|
||||||
cipherSuite uint16
|
cipherSuite uint16
|
||||||
ocspResponse []byte // stapled OCSP response
|
ocspResponse []byte // stapled OCSP response
|
||||||
@ -1670,7 +1671,7 @@ func (c *Conn) connectionStateLocked() ConnectionState {
|
|||||||
state.VerifiedChains = c.verifiedChains
|
state.VerifiedChains = c.verifiedChains
|
||||||
state.SignedCertificateTimestamps = c.scts
|
state.SignedCertificateTimestamps = c.scts
|
||||||
state.OCSPResponse = c.ocspResponse
|
state.OCSPResponse = c.ocspResponse
|
||||||
if !c.didResume && c.vers != VersionTLS13 {
|
if (!c.didResume || c.extMasterSecret) && c.vers != VersionTLS13 {
|
||||||
if c.clientFinishedIsFirst {
|
if c.clientFinishedIsFirst {
|
||||||
state.TLSUnique = c.clientFinished[:]
|
state.TLSUnique = c.clientFinished[:]
|
||||||
} else {
|
} else {
|
||||||
|
@ -72,6 +72,7 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *ecdh.PrivateKey, error) {
|
|||||||
vers: clientHelloVersion,
|
vers: clientHelloVersion,
|
||||||
compressionMethods: []uint8{compressionNone},
|
compressionMethods: []uint8{compressionNone},
|
||||||
random: make([]byte, 32),
|
random: make([]byte, 32),
|
||||||
|
extendedMasterSecret: true,
|
||||||
ocspStapling: true,
|
ocspStapling: true,
|
||||||
scts: true,
|
scts: true,
|
||||||
serverName: hostnameInSNI(config.ServerName),
|
serverName: hostnameInSNI(config.ServerName),
|
||||||
@ -645,6 +646,19 @@ func (hs *clientHandshakeState) doFullHandshake() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if hs.serverHello.extendedMasterSecret {
|
||||||
|
c.extMasterSecret = true
|
||||||
|
hs.masterSecret = extMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret,
|
||||||
|
hs.finishedHash.Sum())
|
||||||
|
} else {
|
||||||
|
hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret,
|
||||||
|
hs.hello.random, hs.serverHello.random)
|
||||||
|
}
|
||||||
|
if err := c.config.writeKeyLog(keyLogLabelTLS12, hs.hello.random, hs.masterSecret); err != nil {
|
||||||
|
c.sendAlert(alertInternalError)
|
||||||
|
return errors.New("tls: failed to write to key log: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
if chainToSend != nil && len(chainToSend.Certificate) > 0 {
|
if chainToSend != nil && len(chainToSend.Certificate) > 0 {
|
||||||
certVerify := &certificateVerifyMsg{}
|
certVerify := &certificateVerifyMsg{}
|
||||||
|
|
||||||
@ -692,12 +706,6 @@ func (hs *clientHandshakeState) doFullHandshake() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.hello.random, hs.serverHello.random)
|
|
||||||
if err := c.config.writeKeyLog(keyLogLabelTLS12, hs.hello.random, hs.masterSecret); err != nil {
|
|
||||||
c.sendAlert(alertInternalError)
|
|
||||||
return errors.New("tls: failed to write to key log: " + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
hs.finishedHash.discardHandshakeBuffer()
|
hs.finishedHash.discardHandshakeBuffer()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -784,8 +792,15 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
|
|||||||
return false, errors.New("tls: server resumed a session with a different cipher suite")
|
return false, errors.New("tls: server resumed a session with a different cipher suite")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RFC 7627, Section 5.3
|
||||||
|
if hs.session.extMasterSecret != hs.serverHello.extendedMasterSecret {
|
||||||
|
c.sendAlert(alertHandshakeFailure)
|
||||||
|
return false, errors.New("tls: server resumed a session with a different EMS extension")
|
||||||
|
}
|
||||||
|
|
||||||
// Restore master secret and certificates from previous state
|
// Restore master secret and certificates from previous state
|
||||||
hs.masterSecret = hs.session.secret
|
hs.masterSecret = hs.session.secret
|
||||||
|
c.extMasterSecret = hs.session.extMasterSecret
|
||||||
c.peerCertificates = hs.session.peerCertificates
|
c.peerCertificates = hs.session.peerCertificates
|
||||||
c.activeCertHandles = hs.c.activeCertHandles
|
c.activeCertHandles = hs.c.activeCertHandles
|
||||||
c.verifiedChains = hs.session.verifiedChains
|
c.verifiedChains = hs.session.verifiedChains
|
||||||
|
@ -136,6 +136,7 @@ func (hs *clientHandshakeStateTLS13) checkServerHelloOrHRR() error {
|
|||||||
|
|
||||||
if hs.serverHello.ocspStapling ||
|
if hs.serverHello.ocspStapling ||
|
||||||
hs.serverHello.ticketSupported ||
|
hs.serverHello.ticketSupported ||
|
||||||
|
hs.serverHello.extendedMasterSecret ||
|
||||||
hs.serverHello.secureRenegotiationSupported ||
|
hs.serverHello.secureRenegotiationSupported ||
|
||||||
len(hs.serverHello.secureRenegotiation) != 0 ||
|
len(hs.serverHello.secureRenegotiation) != 0 ||
|
||||||
len(hs.serverHello.alpnProtocol) != 0 ||
|
len(hs.serverHello.alpnProtocol) != 0 ||
|
||||||
|
@ -84,6 +84,7 @@ type clientHelloMsg struct {
|
|||||||
supportedSignatureAlgorithmsCert []SignatureScheme
|
supportedSignatureAlgorithmsCert []SignatureScheme
|
||||||
secureRenegotiationSupported bool
|
secureRenegotiationSupported bool
|
||||||
secureRenegotiation []byte
|
secureRenegotiation []byte
|
||||||
|
extendedMasterSecret bool
|
||||||
alpnProtocols []string
|
alpnProtocols []string
|
||||||
scts bool
|
scts bool
|
||||||
supportedVersions []uint16
|
supportedVersions []uint16
|
||||||
@ -181,6 +182,11 @@ func (m *clientHelloMsg) marshal() ([]byte, error) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if m.extendedMasterSecret {
|
||||||
|
// RFC 7627
|
||||||
|
exts.AddUint16(extensionExtendedMasterSecret)
|
||||||
|
exts.AddUint16(0) // empty extension_data
|
||||||
|
}
|
||||||
if len(m.alpnProtocols) > 0 {
|
if len(m.alpnProtocols) > 0 {
|
||||||
// RFC 7301, Section 3.1
|
// RFC 7301, Section 3.1
|
||||||
exts.AddUint16(extensionALPN)
|
exts.AddUint16(extensionALPN)
|
||||||
@ -510,6 +516,9 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
m.secureRenegotiationSupported = true
|
m.secureRenegotiationSupported = true
|
||||||
|
case extensionExtendedMasterSecret:
|
||||||
|
// RFC 7627
|
||||||
|
m.extendedMasterSecret = true
|
||||||
case extensionALPN:
|
case extensionALPN:
|
||||||
// RFC 7301, Section 3.1
|
// RFC 7301, Section 3.1
|
||||||
var protoList cryptobyte.String
|
var protoList cryptobyte.String
|
||||||
@ -627,6 +636,7 @@ type serverHelloMsg struct {
|
|||||||
ticketSupported bool
|
ticketSupported bool
|
||||||
secureRenegotiationSupported bool
|
secureRenegotiationSupported bool
|
||||||
secureRenegotiation []byte
|
secureRenegotiation []byte
|
||||||
|
extendedMasterSecret bool
|
||||||
alpnProtocol string
|
alpnProtocol string
|
||||||
scts [][]byte
|
scts [][]byte
|
||||||
supportedVersion uint16
|
supportedVersion uint16
|
||||||
@ -662,6 +672,10 @@ func (m *serverHelloMsg) marshal() ([]byte, error) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if m.extendedMasterSecret {
|
||||||
|
exts.AddUint16(extensionExtendedMasterSecret)
|
||||||
|
exts.AddUint16(0) // empty extension_data
|
||||||
|
}
|
||||||
if len(m.alpnProtocol) > 0 {
|
if len(m.alpnProtocol) > 0 {
|
||||||
exts.AddUint16(extensionALPN)
|
exts.AddUint16(extensionALPN)
|
||||||
exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
|
exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
|
||||||
@ -802,6 +816,8 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
m.secureRenegotiationSupported = true
|
m.secureRenegotiationSupported = true
|
||||||
|
case extensionExtendedMasterSecret:
|
||||||
|
m.extendedMasterSecret = true
|
||||||
case extensionALPN:
|
case extensionALPN:
|
||||||
var protoList cryptobyte.String
|
var protoList cryptobyte.String
|
||||||
if !extData.ReadUint16LengthPrefixed(&protoList) || protoList.Empty() {
|
if !extData.ReadUint16LengthPrefixed(&protoList) || protoList.Empty() {
|
||||||
|
@ -214,6 +214,7 @@ func (hs *serverHandshakeState) processClientHello() error {
|
|||||||
return errors.New("tls: initial handshake had non-empty renegotiation extension")
|
return errors.New("tls: initial handshake had non-empty renegotiation extension")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hs.hello.extendedMasterSecret = hs.clientHello.extendedMasterSecret
|
||||||
hs.hello.secureRenegotiationSupported = hs.clientHello.secureRenegotiationSupported
|
hs.hello.secureRenegotiationSupported = hs.clientHello.secureRenegotiationSupported
|
||||||
hs.hello.compressionMethod = compressionNone
|
hs.hello.compressionMethod = compressionNone
|
||||||
if len(hs.clientHello.serverName) > 0 {
|
if len(hs.clientHello.serverName) > 0 {
|
||||||
@ -471,6 +472,17 @@ func (hs *serverHandshakeState) checkForResumption() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RFC 7627, Section 5.3
|
||||||
|
if !sessionState.extMasterSecret && hs.clientHello.extendedMasterSecret {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if sessionState.extMasterSecret && !hs.clientHello.extendedMasterSecret {
|
||||||
|
// Aborting is somewhat harsh, but it's a MUST and it would indicate a
|
||||||
|
// weird downgrade in client capabilities.
|
||||||
|
return errors.New("tls: session supported extended_master_secret but client does not")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.extMasterSecret = sessionState.extMasterSecret
|
||||||
hs.sessionState = sessionState
|
hs.sessionState = sessionState
|
||||||
hs.suite = suite
|
hs.suite = suite
|
||||||
c.didResume = true
|
c.didResume = true
|
||||||
@ -647,7 +659,14 @@ func (hs *serverHandshakeState) doFullHandshake() error {
|
|||||||
c.sendAlert(alertHandshakeFailure)
|
c.sendAlert(alertHandshakeFailure)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.clientHello.random, hs.hello.random)
|
if hs.hello.extendedMasterSecret {
|
||||||
|
c.extMasterSecret = true
|
||||||
|
hs.masterSecret = extMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret,
|
||||||
|
hs.finishedHash.Sum())
|
||||||
|
} else {
|
||||||
|
hs.masterSecret = masterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret,
|
||||||
|
hs.clientHello.random, hs.hello.random)
|
||||||
|
}
|
||||||
if err := c.config.writeKeyLog(keyLogLabelTLS12, hs.clientHello.random, hs.masterSecret); err != nil {
|
if err := c.config.writeKeyLog(keyLogLabelTLS12, hs.clientHello.random, hs.masterSecret); err != nil {
|
||||||
c.sendAlert(alertInternalError)
|
c.sendAlert(alertInternalError)
|
||||||
return err
|
return err
|
||||||
|
9
prf.go
9
prf.go
@ -80,6 +80,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var masterSecretLabel = []byte("master secret")
|
var masterSecretLabel = []byte("master secret")
|
||||||
|
var extendedMasterSecretLabel = []byte("extended master secret")
|
||||||
var keyExpansionLabel = []byte("key expansion")
|
var keyExpansionLabel = []byte("key expansion")
|
||||||
var clientFinishedLabel = []byte("client finished")
|
var clientFinishedLabel = []byte("client finished")
|
||||||
var serverFinishedLabel = []byte("server finished")
|
var serverFinishedLabel = []byte("server finished")
|
||||||
@ -115,6 +116,14 @@ func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecr
|
|||||||
return masterSecret
|
return masterSecret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extMasterFromPreMasterSecret generates the extended master secret from the
|
||||||
|
// pre-master secret. See RFC 7627.
|
||||||
|
func extMasterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, transcript []byte) []byte {
|
||||||
|
masterSecret := make([]byte, masterSecretLength)
|
||||||
|
prfForVersion(version, suite)(masterSecret, preMasterSecret, extendedMasterSecretLabel, transcript)
|
||||||
|
return masterSecret
|
||||||
|
}
|
||||||
|
|
||||||
// keysFromMasterSecret generates the connection keys from the master
|
// keysFromMasterSecret generates the connection keys from the master
|
||||||
// secret, given the lengths of the MAC key, cipher key and IV, as defined in
|
// secret, given the lengths of the MAC key, cipher key and IV, as defined in
|
||||||
// RFC 2246, Section 6.3.
|
// RFC 2246, Section 6.3.
|
||||||
|
19
ticket.go
19
ticket.go
@ -34,6 +34,7 @@ type SessionState struct {
|
|||||||
// uint64 created_at;
|
// uint64 created_at;
|
||||||
// opaque secret<1..2^8-1>;
|
// opaque secret<1..2^8-1>;
|
||||||
// opaque extra<0..2^24-1>;
|
// opaque extra<0..2^24-1>;
|
||||||
|
// uint8 ext_master_secret = { 0, 1 };
|
||||||
// uint8 early_data = { 0, 1 };
|
// uint8 early_data = { 0, 1 };
|
||||||
// CertificateEntry certificate_list<0..2^24-1>;
|
// CertificateEntry certificate_list<0..2^24-1>;
|
||||||
// select (SessionState.early_data) {
|
// select (SessionState.early_data) {
|
||||||
@ -81,6 +82,7 @@ type SessionState struct {
|
|||||||
// which the ticket was received on the client.
|
// which the ticket was received on the client.
|
||||||
createdAt uint64 // seconds since UNIX epoch
|
createdAt uint64 // seconds since UNIX epoch
|
||||||
secret []byte // master secret for TLS 1.2, or the PSK for TLS 1.3
|
secret []byte // master secret for TLS 1.2, or the PSK for TLS 1.3
|
||||||
|
extMasterSecret bool
|
||||||
peerCertificates []*x509.Certificate
|
peerCertificates []*x509.Certificate
|
||||||
activeCertHandles []*activeCert
|
activeCertHandles []*activeCert
|
||||||
ocspResponse []byte
|
ocspResponse []byte
|
||||||
@ -117,6 +119,11 @@ func (s *SessionState) Bytes() ([]byte, error) {
|
|||||||
b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) {
|
b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) {
|
||||||
b.AddBytes(s.Extra)
|
b.AddBytes(s.Extra)
|
||||||
})
|
})
|
||||||
|
if s.extMasterSecret {
|
||||||
|
b.AddUint8(1)
|
||||||
|
} else {
|
||||||
|
b.AddUint8(0)
|
||||||
|
}
|
||||||
if s.EarlyData {
|
if s.EarlyData {
|
||||||
b.AddUint8(1)
|
b.AddUint8(1)
|
||||||
} else {
|
} else {
|
||||||
@ -173,7 +180,7 @@ func certificatesToBytesSlice(certs []*x509.Certificate) [][]byte {
|
|||||||
func ParseSessionState(data []byte) (*SessionState, error) {
|
func ParseSessionState(data []byte) (*SessionState, error) {
|
||||||
ss := &SessionState{}
|
ss := &SessionState{}
|
||||||
s := cryptobyte.String(data)
|
s := cryptobyte.String(data)
|
||||||
var typ, earlyData uint8
|
var typ, extMasterSecret, earlyData uint8
|
||||||
var cert Certificate
|
var cert Certificate
|
||||||
if !s.ReadUint16(&ss.version) ||
|
if !s.ReadUint16(&ss.version) ||
|
||||||
!s.ReadUint8(&typ) ||
|
!s.ReadUint8(&typ) ||
|
||||||
@ -182,11 +189,20 @@ func ParseSessionState(data []byte) (*SessionState, error) {
|
|||||||
!readUint64(&s, &ss.createdAt) ||
|
!readUint64(&s, &ss.createdAt) ||
|
||||||
!readUint8LengthPrefixed(&s, &ss.secret) ||
|
!readUint8LengthPrefixed(&s, &ss.secret) ||
|
||||||
!readUint24LengthPrefixed(&s, &ss.Extra) ||
|
!readUint24LengthPrefixed(&s, &ss.Extra) ||
|
||||||
|
!s.ReadUint8(&extMasterSecret) ||
|
||||||
!s.ReadUint8(&earlyData) ||
|
!s.ReadUint8(&earlyData) ||
|
||||||
len(ss.secret) == 0 ||
|
len(ss.secret) == 0 ||
|
||||||
!unmarshalCertificate(&s, &cert) {
|
!unmarshalCertificate(&s, &cert) {
|
||||||
return nil, errors.New("tls: invalid session encoding")
|
return nil, errors.New("tls: invalid session encoding")
|
||||||
}
|
}
|
||||||
|
switch extMasterSecret {
|
||||||
|
case 0:
|
||||||
|
ss.extMasterSecret = false
|
||||||
|
case 1:
|
||||||
|
ss.extMasterSecret = true
|
||||||
|
default:
|
||||||
|
return nil, errors.New("tls: invalid session encoding")
|
||||||
|
}
|
||||||
switch earlyData {
|
switch earlyData {
|
||||||
case 0:
|
case 0:
|
||||||
ss.EarlyData = false
|
ss.EarlyData = false
|
||||||
@ -279,6 +295,7 @@ func (c *Conn) sessionState() (*SessionState, error) {
|
|||||||
ocspResponse: c.ocspResponse,
|
ocspResponse: c.ocspResponse,
|
||||||
scts: c.scts,
|
scts: c.scts,
|
||||||
isClient: c.isClient,
|
isClient: c.isClient,
|
||||||
|
extMasterSecret: c.extMasterSecret,
|
||||||
verifiedChains: verifiedChains,
|
verifiedChains: verifiedChains,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user