Skip to content

Commit ead11a3

Browse files
committed
Implement TLS Flags and the request mTLS flag.
1 parent 087d810 commit ead11a3

File tree

5 files changed

+119
-1
lines changed

5 files changed

+119
-1
lines changed

src/crypto/tls/common.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ const (
126126
extensionRenegotiationInfo uint16 = 0xff01
127127
extensionECH uint16 = 0xfe0d // draft-ietf-tls-esni-13
128128
extensionECHOuterExtensions uint16 = 0xfd00 // draft-ietf-tls-esni-13
129+
extensionTLSFlags uint16 = 0xfe01 // draft-ietf-tls-tlsflags-12
129130
)
130131

131132
// TLS signaling cipher suite values
@@ -363,6 +364,15 @@ type ConnectionState struct {
363364
// This means the client has offered ECH or sent GREASE ECH.
364365
ECHOffered bool
365366

367+
// PeerTLSFlags is the set of TLS Flags sent by the Peer.
368+
PeerTLSFlags []TLSFlag
369+
370+
// AgreedTLSFlags is the set of TLS Flags mutually supported by the Client and Server
371+
AgreedTLSFlags []TLSFlag
372+
373+
// RequestClientCert is true if the server decided to request a client certificate
374+
RequestClientCert bool
375+
366376
// ekm is a closure exposed via ExportKeyingMaterial.
367377
ekm func(label string, context []byte, length int) ([]byte, error)
368378
}
@@ -468,6 +478,12 @@ const (
468478
ECDSAWithSHA1 SignatureScheme = 0x0203
469479
)
470480

481+
type TLSFlag uint16
482+
483+
const (
484+
FlagSupportMTLS TLSFlag = 0x50
485+
)
486+
471487
// ClientHelloInfo contains information from a ClientHello message in order to
472488
// guide application logic in the GetCertificate and GetConfigForClient callbacks.
473489
type ClientHelloInfo struct {
@@ -904,6 +920,8 @@ type Config struct {
904920
// See https://tools.ietf.org/html/draft-ietf-tls-subcerts.
905921
SupportDelegatedCredential bool
906922

923+
TLSFlagsSupported []TLSFlag
924+
907925
// mutex protects sessionTicketKeys and autoSessionTicketKeys.
908926
mutex sync.RWMutex
909927
// sessionTicketKeys contains zero or more ticket keys. If set, it means
@@ -994,6 +1012,7 @@ func (c *Config) Clone() *Config {
9941012
Renegotiation: c.Renegotiation,
9951013
KeyLogWriter: c.KeyLogWriter,
9961014
SupportDelegatedCredential: c.SupportDelegatedCredential,
1015+
TLSFlagsSupported: c.TLSFlagsSupported,
9971016
ECHEnabled: c.ECHEnabled,
9981017
ClientECHConfigs: c.ClientECHConfigs,
9991018
ServerECHProvider: c.ServerECHProvider,

src/crypto/tls/conn.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ type Conn struct {
143143
configId uint8 // The ECH config id
144144
maxNameLen int // maximum_name_len indicated by the ECH config
145145
}
146+
147+
agreedTLSFlags []TLSFlag
148+
peerTLSFlags []TLSFlag
149+
requestClientCert bool
146150
}
147151

148152
// Access to net.Conn methods.
@@ -1696,6 +1700,9 @@ func (c *Conn) connectionStateLocked() ConnectionState {
16961700
} else {
16971701
state.ekm = c.ekm
16981702
}
1703+
state.PeerTLSFlags = c.peerTLSFlags
1704+
state.AgreedTLSFlags = c.agreedTLSFlags
1705+
state.RequestClientCert = c.requestClientCert
16991706
return state
17001707
}
17011708

src/crypto/tls/handshake_client.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,11 @@ func (c *Conn) makeClientHello(minVersion uint16) (*clientHelloMsg, clientKeySha
218218

219219
hello.delegatedCredentialSupported = config.SupportDelegatedCredential
220220
hello.supportedSignatureAlgorithmsDC = supportedSignatureAlgorithmsDC
221+
flagBytes, err := encodeFlags(config.TLSFlagsSupported)
222+
if err != nil {
223+
return nil, nil, err
224+
}
225+
hello.tlsFlags = flagBytes
221226
}
222227

223228
if c.quic != nil {
@@ -234,6 +239,23 @@ func (c *Conn) makeClientHello(minVersion uint16) (*clientHelloMsg, clientKeySha
234239
return hello, secret, nil
235240
}
236241

242+
const maxTLSFlag = TLSFlag(2040)
243+
244+
func encodeFlags(flags []TLSFlag) ([]byte, error) {
245+
flagBytes := make([]byte, 0, 255)
246+
for _, flag := range flags {
247+
if flag >= maxTLSFlag {
248+
return nil, fmt.Errorf("cannot encode TLS flags greater than %d", maxTLSFlag)
249+
}
250+
whichByte := int(flag) >> 3
251+
if whichByte >= len(flagBytes) {
252+
flagBytes = flagBytes[:whichByte+1]
253+
}
254+
flagBytes[whichByte] |= 1 << (flag % 8)
255+
}
256+
return flagBytes, nil
257+
}
258+
237259
func (c *Conn) clientHandshake(ctx context.Context) (err error) {
238260
if c.config == nil {
239261
c.config = defaultConfig()

src/crypto/tls/handshake_messages.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ type clientHelloMsg struct {
9090
alpnProtocols []string
9191
scts bool
9292
supportedVersions []uint16
93+
tlsFlags []byte
9394
cookie []byte
9495
keyShares []keyShare
9596
earlyData bool
@@ -239,6 +240,14 @@ func (m *clientHelloMsg) marshal() ([]byte, error) {
239240
})
240241
})
241242
}
243+
if len(m.tlsFlags) > 0 {
244+
exts.AddUint16(extensionTLSFlags)
245+
exts.AddUint16LengthPrefixed(func(exts *cryptobyte.Builder) {
246+
exts.AddUint8LengthPrefixed(func(exts *cryptobyte.Builder) {
247+
exts.AddBytes(m.tlsFlags)
248+
})
249+
})
250+
}
242251
if len(m.cookie) > 0 {
243252
// RFC 8446, Section 4.2.2
244253
exts.AddUint16(extensionCookie)
@@ -577,6 +586,18 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
577586
}
578587
m.supportedVersions = append(m.supportedVersions, vers)
579588
}
589+
case extensionTLSFlags:
590+
var flagsList cryptobyte.String
591+
if !extData.ReadUint8LengthPrefixed(&flagsList) || flagsList.Empty() {
592+
return false
593+
}
594+
for !flagsList.Empty() {
595+
var flagByte uint8
596+
if !flagsList.ReadUint8(&flagByte) {
597+
return false
598+
}
599+
m.tlsFlags = append(m.tlsFlags, flagByte)
600+
}
580601
case extensionCookie:
581602
// RFC 8446, Section 4.2.2
582603
if !readUint16LengthPrefixed(&extData, &m.cookie) ||

src/crypto/tls/handshake_server_tls13.go

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ type serverHandshakeStateTLS13 struct {
4343
transcript hash.Hash
4444
clientFinished []byte
4545
certReq *certificateRequestMsgTLS13
46+
peerTLSFlags []TLSFlag
47+
tlsFlags []TLSFlag
4648

4749
hsTimings CFEventTLS13ServerHandshakeTimingInfo
4850
}
@@ -132,7 +134,9 @@ func (hs *serverHandshakeStateTLS13) handshake() error {
132134

133135
c.handleCFEvent(hs.hsTimings)
134136
c.isHandshakeComplete.Store(true)
135-
137+
c.agreedTLSFlags = hs.tlsFlags
138+
c.peerTLSFlags = hs.peerTLSFlags
139+
c.requestClientCert = hs.requestClientCert()
136140
return nil
137141
}
138142

@@ -317,6 +321,29 @@ GroupSelection:
317321
c.sendAlert(alertIllegalParameter)
318322
return errors.New("tls: invalid client key share")
319323
}
324+
if len(hs.clientHello.tlsFlags) != 0 {
325+
supportedFlags, err := encodeFlags(hs.c.config.TLSFlagsSupported)
326+
if err != nil {
327+
return errors.New("tls: invalid server flags")
328+
}
329+
var mutuallySupportedFlags []byte
330+
for i, sFB := range supportedFlags {
331+
if i >= len(hs.clientHello.tlsFlags) {
332+
break
333+
}
334+
mutuallySupportedFlags = append(mutuallySupportedFlags, hs.clientHello.tlsFlags[i]&sFB)
335+
}
336+
337+
peerTLSFlags, err := decodeFlags(hs.clientHello.tlsFlags)
338+
if err == nil {
339+
hs.peerTLSFlags = peerTLSFlags
340+
}
341+
342+
tlsFlags, err := decodeFlags(mutuallySupportedFlags)
343+
if err == nil {
344+
hs.tlsFlags = tlsFlags
345+
}
346+
}
320347

321348
selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols, c.quic != nil)
322349
if err != nil {
@@ -356,6 +383,23 @@ GroupSelection:
356383
return nil
357384
}
358385

386+
func decodeFlags(flagBytes []byte) ([]TLSFlag, error) {
387+
var flags []TLSFlag
388+
for byteIndex, b := range flagBytes {
389+
for i := 0; !(b == 0); i++ {
390+
if (b & 1) == 1 {
391+
flagNo := byteIndex*8 + i
392+
if flagNo >= int(maxTLSFlag) {
393+
return nil, fmt.Errorf("TLS flag is out of range: %d", flagNo)
394+
}
395+
flags = append(flags, TLSFlag(flagNo))
396+
}
397+
b >>= 1
398+
}
399+
}
400+
return flags, nil
401+
}
402+
359403
func (hs *serverHandshakeStateTLS13) checkForResumption() error {
360404
c := hs.c
361405

@@ -892,6 +936,11 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error {
892936
}
893937

894938
func (hs *serverHandshakeStateTLS13) requestClientCert() bool {
939+
for _, flag := range hs.tlsFlags {
940+
if flag == FlagSupportMTLS {
941+
return true
942+
}
943+
}
895944
return hs.c.config.ClientAuth >= RequestClientCert && !hs.usingPSK
896945
}
897946

0 commit comments

Comments
 (0)