crypto/tls: make SessionState.Extra a slice of byte slices

Fixes #60539
Updates #60105

Change-Id: I7b567cc1d0901891ed97d29591db935cd487cc71
Reviewed-on: https://go-review.googlesource.com/c/go/+/501675
Auto-Submit: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
Filippo Valsorda 2023-06-07 21:36:19 +02:00 committed by Gopher Robot
parent 1f11ea6c41
commit 6801c27837
3 changed files with 27 additions and 10 deletions

View file

@ -80,7 +80,7 @@ pkg crypto/tls, type QUICEvent struct, Level QUICEncryptionLevel #44886
pkg crypto/tls, type QUICEvent struct, Suite uint16 #44886
pkg crypto/tls, type SessionState struct #60105
pkg crypto/tls, type SessionState struct, EarlyData bool #60107
pkg crypto/tls, type SessionState struct, Extra []uint8 #60105
pkg crypto/tls, type SessionState struct, Extra [][]uint8 #60539
pkg crypto/x509, type RevocationListEntry struct #53573
pkg crypto/x509, type RevocationListEntry struct, Extensions []pkix.Extension #53573
pkg crypto/x509, type RevocationListEntry struct, ExtraExtensions []pkix.Extension #53573

View file

@ -355,7 +355,9 @@ func (*SessionState) Generate(rand *rand.Rand, size int) reflect.Value {
s.cipherSuite = uint16(rand.Intn(math.MaxUint16))
s.createdAt = uint64(rand.Int63())
s.secret = randomBytes(rand.Intn(100)+1, rand)
s.Extra = randomBytes(rand.Intn(100), rand)
for n, i := rand.Intn(3), 0; i < n; i++ {
s.Extra = append(s.Extra, randomBytes(rand.Intn(100), rand))
}
if rand.Intn(10) > 5 {
s.EarlyData = true
}

View file

@ -27,13 +27,15 @@ type SessionState struct {
//
// Certificate CertificateChain<0..2^24-1>;
//
// opaque Extra<0..2^24-1>;
//
// struct {
// uint16 version;
// SessionStateType type;
// uint16 cipher_suite;
// uint64 created_at;
// opaque secret<1..2^8-1>;
// opaque extra<0..2^24-1>;
// Extra extra<0..2^24-1>;
// uint8 ext_master_secret = { 0, 1 };
// uint8 early_data = { 0, 1 };
// CertificateEntry certificate_list<0..2^24-1>;
@ -62,12 +64,13 @@ type SessionState struct {
//
// This allows [Config.UnwrapSession]/[Config.WrapSession] and
// [ClientSessionCache] implementations to store and retrieve additional
// data.
// data alongside this session.
//
// If Extra is already set, the implementation must preserve the previous
// value across a round-trip, for example by appending and stripping a
// fixed-length suffix.
Extra []byte
// To allow different layers in a protocol stack to share this field,
// applications must only append to it, not replace it, and must use entries
// that can be recognized even if out of order (for example, by starting
// with a id and version prefix).
Extra [][]byte
// EarlyData indicates whether the ticket can be used for 0-RTT in a QUIC
// connection. The application may set this to false if it is true to
@ -115,7 +118,11 @@ func (s *SessionState) Bytes() ([]byte, error) {
b.AddBytes(s.secret)
})
b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) {
b.AddBytes(s.Extra)
for _, extra := range s.Extra {
b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) {
b.AddBytes(extra)
})
}
})
if s.extMasterSecret {
b.AddUint8(1)
@ -176,19 +183,27 @@ func ParseSessionState(data []byte) (*SessionState, error) {
s := cryptobyte.String(data)
var typ, extMasterSecret, earlyData uint8
var cert Certificate
var extra cryptobyte.String
if !s.ReadUint16(&ss.version) ||
!s.ReadUint8(&typ) ||
(typ != 1 && typ != 2) ||
!s.ReadUint16(&ss.cipherSuite) ||
!readUint64(&s, &ss.createdAt) ||
!readUint8LengthPrefixed(&s, &ss.secret) ||
!readUint24LengthPrefixed(&s, &ss.Extra) ||
!s.ReadUint24LengthPrefixed(&extra) ||
!s.ReadUint8(&extMasterSecret) ||
!s.ReadUint8(&earlyData) ||
len(ss.secret) == 0 ||
!unmarshalCertificate(&s, &cert) {
return nil, errors.New("tls: invalid session encoding")
}
for !extra.Empty() {
var e []byte
if !readUint24LengthPrefixed(&extra, &e) {
return nil, errors.New("tls: invalid session encoding")
}
ss.Extra = append(ss.Extra, e)
}
switch extMasterSecret {
case 0:
ss.extMasterSecret = false