mirror of
https://github.com/refraction-networking/utls.git
synced 2025-04-04 04:27:36 +03:00
crypto/tls: implement TLS 1.3 PSK authentication (client side)
Also check original certificate validity when resuming TLS 1.0–1.2. Will refuse to resume a session if the certificate is expired or if the original connection had InsecureSkipVerify and the resumed one doesn't. Support only PSK+DHE to protect forward secrecy even with lack of a strong session ticket rotation story. Tested with NSS because s_server does not provide any way of getting the same session ticket key across invocations. Will self-test like TLS 1.0–1.2 once server side is implemented. Incorporates CL 128477 by @santoshankr. Fixes #24919 Updates #9671 Change-Id: Id3eaa5b6c77544a1357668bf9ff255f3420ecc34 Reviewed-on: https://go-review.googlesource.com/c/147420 Reviewed-by: Adam Langley <agl@golang.org>
This commit is contained in:
parent
5b79a7c982
commit
dc9021e679
11 changed files with 444 additions and 158 deletions
44
common.go
44
common.go
|
@ -240,22 +240,32 @@ type ClientSessionState struct {
|
|||
sessionTicket []uint8 // Encrypted ticket used for session resumption with server
|
||||
vers uint16 // SSL/TLS version negotiated for the session
|
||||
cipherSuite uint16 // Ciphersuite negotiated for the session
|
||||
masterSecret []byte // MasterSecret generated by client on a full handshake
|
||||
masterSecret []byte // Full handshake MasterSecret, or TLS 1.3 resumption_master_secret
|
||||
serverCertificates []*x509.Certificate // Certificate chain presented by the server
|
||||
verifiedChains [][]*x509.Certificate // Certificate chains we built for verification
|
||||
receivedAt time.Time // When the session ticket was received from the server
|
||||
|
||||
// TLS 1.3 fields.
|
||||
nonce []byte // Ticket nonce sent by the server, to derive PSK
|
||||
useBy time.Time // Expiration of the ticket lifetime as set by the server
|
||||
ageAdd uint32 // Random obfuscation factor for sending the ticket age
|
||||
}
|
||||
|
||||
// ClientSessionCache is a cache of ClientSessionState objects that can be used
|
||||
// by a client to resume a TLS session with a given server. ClientSessionCache
|
||||
// implementations should expect to be called concurrently from different
|
||||
// goroutines. Only ticket-based resumption is supported, not SessionID-based
|
||||
// resumption.
|
||||
// goroutines. Up to TLS 1.2, only ticket-based resumption is supported, not
|
||||
// SessionID-based resumption. In TLS 1.3 they were merged into PSK modes, which
|
||||
// are supported via this interface.
|
||||
type ClientSessionCache interface {
|
||||
// Get searches for a ClientSessionState associated with the given key.
|
||||
// On return, ok is true if one was found.
|
||||
Get(sessionKey string) (session *ClientSessionState, ok bool)
|
||||
|
||||
// Put adds the ClientSessionState to the cache with the given key.
|
||||
// Put adds the ClientSessionState to the cache with the given key. It might
|
||||
// get called multiple times in a connection if a TLS 1.3 server provides
|
||||
// more than one session ticket. If called with a nil *ClientSessionState,
|
||||
// it should remove the cache entry.
|
||||
Put(sessionKey string, cs *ClientSessionState)
|
||||
}
|
||||
|
||||
|
@ -502,19 +512,19 @@ type Config struct {
|
|||
// the order of elements in CipherSuites, is used.
|
||||
PreferServerCipherSuites bool
|
||||
|
||||
// SessionTicketsDisabled may be set to true to disable session ticket
|
||||
// (resumption) support. Note that on clients, session ticket support is
|
||||
// SessionTicketsDisabled may be set to true to disable session ticket and
|
||||
// PSK (resumption) support. Note that on clients, session ticket support is
|
||||
// also disabled if ClientSessionCache is nil.
|
||||
SessionTicketsDisabled bool
|
||||
|
||||
// SessionTicketKey is used by TLS servers to provide session
|
||||
// resumption. See RFC 5077. If zero, it will be filled with
|
||||
// random data before the first server handshake.
|
||||
// SessionTicketKey is used by TLS servers to provide session resumption.
|
||||
// See RFC 5077 and the PSK mode of RFC 8446. If zero, it will be filled
|
||||
// with random data before the first server handshake.
|
||||
//
|
||||
// If multiple servers are terminating connections for the same host
|
||||
// they should all have the same SessionTicketKey. If the
|
||||
// SessionTicketKey leaks, previously recorded and future TLS
|
||||
// connections using that key are compromised.
|
||||
// connections using that key might be compromised.
|
||||
SessionTicketKey [32]byte
|
||||
|
||||
// ClientSessionCache is a cache of ClientSessionState entries for TLS
|
||||
|
@ -937,15 +947,21 @@ func NewLRUClientSessionCache(capacity int) ClientSessionCache {
|
|||
}
|
||||
}
|
||||
|
||||
// Put adds the provided (sessionKey, cs) pair to the cache.
|
||||
// Put adds the provided (sessionKey, cs) pair to the cache. If cs is nil, the entry
|
||||
// corresponding to sessionKey is removed from the cache instead.
|
||||
func (c *lruSessionCache) Put(sessionKey string, cs *ClientSessionState) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
if elem, ok := c.m[sessionKey]; ok {
|
||||
entry := elem.Value.(*lruSessionCacheEntry)
|
||||
entry.state = cs
|
||||
c.q.MoveToFront(elem)
|
||||
if cs == nil {
|
||||
c.q.Remove(elem)
|
||||
delete(c.m, sessionKey)
|
||||
} else {
|
||||
entry := elem.Value.(*lruSessionCacheEntry)
|
||||
entry.state = cs
|
||||
c.q.MoveToFront(elem)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue