Skip to content

Commit 0557f61

Browse files
BRUHItsABunnymingyech
authored andcommitted
feat: support new codepoint in ECH
1 parent 5c20b85 commit 0557f61

File tree

7 files changed

+103
-109
lines changed

7 files changed

+103
-109
lines changed

dicttls/exttype_values.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ const (
6969
const (
7070
ExtType_next_protocol_negotiation uint16 = 13172 // https://datatracker.ietf.org/doc/html/draft-agl-tls-nextprotoneg-04
7171
ExtType_application_settings uint16 = 17513 // https://www.ietf.org/archive/id/draft-vvv-tls-alps-01.html
72+
ExtType_application_settings_new uint16 = 17613 // https://www.ietf.org/archive/id/draft-vvv-tls-alps-01.html
7273
ExtType_channel_id_old uint16 = 30031 // https://datatracker.ietf.org/doc/html/draft-balfanz-tls-channelid-01
7374
ExtType_channel_id uint16 = 30032 // https://datatracker.ietf.org/doc/html/draft-balfanz-tls-channelid-01
7475
)
@@ -136,6 +137,7 @@ var DictExtTypeValueIndexed = map[uint16]string{
136137

137138
13172: "next_protocol_negotiation",
138139
17513: "application_settings",
140+
17613: "application_settings_new",
139141
30031: "channel_id_old",
140142
30032: "channel_id",
141143
}
@@ -204,6 +206,7 @@ var DictExtTypeNameIndexed = map[string]uint16{
204206

205207
"next_protocol_negotiation": 13172,
206208
"application_settings": 17513,
209+
"application_settings_new": 17613,
207210
"channel_id_old": 30031,
208211
"channel_id": 30032,
209212
}

u_common.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,13 @@ const (
3434
const (
3535
extensionNextProtoNeg uint16 = 13172 // not IANA assigned. Removed by crypto/tls since Nov 2019
3636

37-
utlsExtensionPadding uint16 = 21
38-
utlsExtensionCompressCertificate uint16 = 27 // https://datatracker.ietf.org/doc/html/rfc8879#section-7.1
39-
utlsExtensionApplicationSettings uint16 = 17513 // not IANA assigned
40-
utlsFakeExtensionCustom uint16 = 1234 // not IANA assigned, for ALPS
41-
utlsExtensionECH uint16 = 0xfe0d // draft-ietf-tls-esni-17
42-
utlsExtensionECHOuterExtensions uint16 = 0xfd00 // draft-ietf-tls-esni-17
37+
utlsExtensionPadding uint16 = 21
38+
utlsExtensionCompressCertificate uint16 = 27 // https://datatracker.ietf.org/doc/html/rfc8879#section-7.1
39+
utlsExtensionApplicationSettings uint16 = 17513 // not IANA assigned
40+
utlsExtensionApplicationSettingsNew uint16 = 17613 // not IANA assigned
41+
utlsFakeExtensionCustom uint16 = 1234 // not IANA assigned, for ALPS
42+
utlsExtensionECH uint16 = 0xfe0d // draft-ietf-tls-esni-17
43+
utlsExtensionECHOuterExtensions uint16 = 0xfd00 // draft-ietf-tls-esni-17
4344

4445
// extensions with 'fake' prefix break connection, if server echoes them back
4546
fakeExtensionEncryptThenMAC uint16 = 22
@@ -447,6 +448,8 @@ func (chs *ClientHelloSpec) ImportTLSClientHello(data map[string][]byte) error {
447448
case utlsExtensionApplicationSettings:
448449
// TODO: tlsfingerprint.io should record/provide application settings data
449450
extWriter.(*ApplicationSettingsExtension).SupportedProtocols = []string{"h2"}
451+
case utlsExtensionApplicationSettingsNew:
452+
extWriter.(*ApplicationSettingsExtensionNew).SupportedProtocols = []string{"h2"}
450453
case extensionPreSharedKey:
451454
log.Printf("[Warning] PSK extension added without data")
452455
default:

u_conn.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -846,9 +846,9 @@ func (c *Conn) utlsConnectionStateLocked(state *ConnectionState) {
846846

847847
type utlsConnExtraFields struct {
848848
// Application Settings (ALPS)
849-
hasApplicationSettings bool
850-
peerApplicationSettings []byte
851-
localApplicationSettings []byte
849+
peerApplicationSettings []byte
850+
localApplicationSettings []byte
851+
applicationSettingsCodepoint uint16
852852

853853
// Encrypted Client Hello (ECH)
854854
echRetryConfigs []ECHConfig

u_handshake_client.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@ func (hs *clientHandshakeStateTLS13) serverFinishedReceived() error {
131131
func (hs *clientHandshakeStateTLS13) sendClientEncryptedExtensions() error {
132132
c := hs.c
133133
clientEncryptedExtensions := new(utlsClientEncryptedExtensionsMsg)
134-
if c.utls.hasApplicationSettings {
135-
clientEncryptedExtensions.hasApplicationSettings = true
134+
if c.utls.applicationSettingsCodepoint != 0 {
135+
clientEncryptedExtensions.applicationSettingsCodepoint = c.utls.applicationSettingsCodepoint
136136
clientEncryptedExtensions.applicationSettings = c.utls.localApplicationSettings
137137
if _, err := c.writeHandshakeRecord(clientEncryptedExtensions, hs.transcript); err != nil {
138138
return err
@@ -143,11 +143,11 @@ func (hs *clientHandshakeStateTLS13) sendClientEncryptedExtensions() error {
143143
}
144144

145145
func (hs *clientHandshakeStateTLS13) utlsReadServerParameters(encryptedExtensions *encryptedExtensionsMsg) error {
146-
hs.c.utls.hasApplicationSettings = encryptedExtensions.utls.hasApplicationSettings
147146
hs.c.utls.peerApplicationSettings = encryptedExtensions.utls.applicationSettings
147+
hs.c.utls.applicationSettingsCodepoint = encryptedExtensions.utls.applicationSettingsCodepoint
148148
hs.c.utls.echRetryConfigs = encryptedExtensions.utls.echRetryConfigs
149149

150-
if hs.c.utls.hasApplicationSettings {
150+
if hs.c.utls.applicationSettingsCodepoint != 0 {
151151
if hs.uconn.vers < VersionTLS13 {
152152
return errors.New("tls: server sent application settings at invalid version")
153153
}

u_handshake_messages.go

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,18 @@ func (m *utlsCompressedCertificateMsg) unmarshal(data []byte) bool {
5454
}
5555

5656
type utlsEncryptedExtensionsMsgExtraFields struct {
57-
hasApplicationSettings bool
58-
applicationSettings []byte
59-
echRetryConfigs []ECHConfig
60-
customExtension []byte
57+
applicationSettings []byte
58+
applicationSettingsCodepoint uint16
59+
echRetryConfigs []ECHConfig
60+
customExtension []byte
6161
}
6262

6363
func (m *encryptedExtensionsMsg) utlsUnmarshal(extension uint16, extData cryptobyte.String) bool {
6464
switch extension {
6565
case utlsExtensionApplicationSettings:
66-
m.utls.hasApplicationSettings = true
66+
fallthrough
67+
case utlsExtensionApplicationSettingsNew:
68+
m.utls.applicationSettingsCodepoint = extension
6769
m.utls.applicationSettings = []byte(extData)
6870
case utlsExtensionECH:
6971
var err error
@@ -76,10 +78,10 @@ func (m *encryptedExtensionsMsg) utlsUnmarshal(extension uint16, extData cryptob
7678
}
7779

7880
type utlsClientEncryptedExtensionsMsg struct {
79-
raw []byte
80-
applicationSettings []byte
81-
hasApplicationSettings bool
82-
customExtension []byte
81+
raw []byte
82+
applicationSettings []byte
83+
applicationSettingsCodepoint uint16
84+
customExtension []byte
8385
}
8486

8587
func (m *utlsClientEncryptedExtensionsMsg) marshal() (x []byte, err error) {
@@ -91,8 +93,8 @@ func (m *utlsClientEncryptedExtensionsMsg) marshal() (x []byte, err error) {
9193
builder.AddUint8(typeEncryptedExtensions)
9294
builder.AddUint24LengthPrefixed(func(body *cryptobyte.Builder) {
9395
body.AddUint16LengthPrefixed(func(extensions *cryptobyte.Builder) {
94-
if m.hasApplicationSettings {
95-
extensions.AddUint16(utlsExtensionApplicationSettings)
96+
if m.applicationSettingsCodepoint != 0 {
97+
extensions.AddUint16(m.applicationSettingsCodepoint)
9698
extensions.AddUint16LengthPrefixed(func(msg *cryptobyte.Builder) {
9799
msg.AddBytes(m.applicationSettings)
98100
})
@@ -130,7 +132,9 @@ func (m *utlsClientEncryptedExtensionsMsg) unmarshal(data []byte) bool {
130132

131133
switch extension {
132134
case utlsExtensionApplicationSettings:
133-
m.hasApplicationSettings = true
135+
fallthrough
136+
case utlsExtensionApplicationSettingsNew:
137+
m.applicationSettingsCodepoint = extension
134138
m.applicationSettings = []byte(extData)
135139
default:
136140
// Unknown extensions are illegal in EncryptedExtensions.

u_parrots.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -948,8 +948,7 @@ func utlsIdToSpec(id ClientHelloID) (ClientHelloSpec, error) {
948948
&UtlsCompressCertExtension{[]CertCompressionAlgo{
949949
CertCompressionBrotli,
950950
}},
951-
&ApplicationSettingsExtensionNew{&ApplicationSettingsExtension{SupportedProtocols: []string{"h2"}}},
952-
// &ApplicationSettingsExtension{SupportedProtocols: []string{"h2"}},
951+
&ApplicationSettingsExtensionNew{SupportedProtocols: []string{"h2"}},
953952
BoringGREASEECH(),
954953
&UtlsGREASEExtension{},
955954
}),

u_tls_extensions.go

Lines changed: 67 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ func ExtensionFromID(id uint16) TLSExtension {
7171
return &NPNExtension{}
7272
case utlsExtensionApplicationSettings:
7373
return &ApplicationSettingsExtension{}
74+
case utlsExtensionApplicationSettingsNew:
75+
return &ApplicationSettingsExtensionNew{}
7476
case fakeOldExtensionChannelID:
7577
return &FakeChannelIDExtension{true}
7678
case fakeExtensionChannelID:
@@ -684,39 +686,39 @@ func (e *ALPNExtension) Write(b []byte) (int, error) {
684686
return fullLen, nil
685687
}
686688

687-
// ApplicationSettingsExtension represents the TLS ALPS extension.
689+
// applicationSettingsExtension represents the TLS ALPS extension.
688690
// At the time of this writing, this extension is currently a draft:
689691
// https://datatracker.ietf.org/doc/html/draft-vvv-tls-alps-01
690-
type ApplicationSettingsExtension struct {
691-
SupportedProtocols []string
692+
type applicationSettingsExtension struct {
693+
codePoint uint16
692694
}
693695

694-
func (e *ApplicationSettingsExtension) writeToUConn(uc *UConn) error {
696+
func (e *applicationSettingsExtension) writeToUConn(uc *UConn) error {
695697
return nil
696698
}
697699

698-
func (e *ApplicationSettingsExtension) Len() int {
700+
func (e *applicationSettingsExtension) Len(supportedProtocols []string) int {
699701
bLen := 2 + 2 + 2 // Type + Length + ALPS Extension length
700-
for _, s := range e.SupportedProtocols {
702+
for _, s := range supportedProtocols {
701703
bLen += 1 + len(s) // Supported ALPN Length + actual length of protocol
702704
}
703705
return bLen
704706
}
705707

706-
func (e *ApplicationSettingsExtension) Read(b []byte) (int, error) {
707-
if len(b) < e.Len() {
708+
func (e *applicationSettingsExtension) Read(b []byte, supportedProtocols []string) (int, error) {
709+
if len(b) < e.Len(supportedProtocols) {
708710
return 0, io.ErrShortBuffer
709711
}
710712

711713
// Read Type.
712-
b[0] = byte(utlsExtensionApplicationSettings >> 8) // hex: 44 dec: 68
713-
b[1] = byte(utlsExtensionApplicationSettings & 0xff) // hex: 69 dec: 105
714+
b[0] = byte(e.codePoint >> 8) // hex: 44 dec: 68
715+
b[1] = byte(e.codePoint & 0xff) // hex: 69 dec: 105
714716

715717
lengths := b[2:] // get the remaining buffer without Type
716718
b = b[6:] // set the buffer to the buffer without Type, Length and ALPS Extension Length (so only the Supported ALPN list remains)
717719

718720
stringsLength := 0
719-
for _, s := range e.SupportedProtocols {
721+
for _, s := range supportedProtocols {
720722
l := len(s) // Supported ALPN Length
721723
b[0] = byte(l) // Supported ALPN Length in bytes hex: 02 dec: 2
722724
copy(b[1:], s) // copy the Supported ALPN as bytes to the buffer
@@ -730,92 +732,87 @@ func (e *ApplicationSettingsExtension) Read(b []byte) (int, error) {
730732
lengths[0] = byte(stringsLength >> 8) // Length hex:00 dec: 0
731733
lengths[1] = byte(stringsLength) // Length hex: 05 dec: 5
732734

733-
return e.Len(), io.EOF
734-
}
735-
736-
func (e *ApplicationSettingsExtension) UnmarshalJSON(b []byte) error {
737-
var applicationSettingsSupport struct {
738-
SupportedProtocols []string `json:"supported_protocols"`
739-
}
740-
741-
if err := json.Unmarshal(b, &applicationSettingsSupport); err != nil {
742-
return err
743-
}
744-
745-
e.SupportedProtocols = applicationSettingsSupport.SupportedProtocols
746-
return nil
735+
return e.Len(supportedProtocols), io.EOF
747736
}
748737

749738
// Write implementation copied from ALPNExtension.Write
750-
func (e *ApplicationSettingsExtension) Write(b []byte) (int, error) {
739+
func (e *applicationSettingsExtension) Write(b []byte) ([]string, int, error) {
751740
fullLen := len(b)
752741
extData := cryptobyte.String(b)
753742
// https://datatracker.ietf.org/doc/html/draft-vvv-tls-alps-01
754743
var protoList cryptobyte.String
755744
if !extData.ReadUint16LengthPrefixed(&protoList) || protoList.Empty() {
756-
return 0, errors.New("unable to read ALPN extension data")
745+
return nil, 0, errors.New("unable to read ALPN extension data")
757746
}
758747
alpnProtocols := []string{}
759748
for !protoList.Empty() {
760749
var proto cryptobyte.String
761750
if !protoList.ReadUint8LengthPrefixed(&proto) || proto.Empty() {
762-
return 0, errors.New("unable to read ALPN extension data")
751+
return nil, 0, errors.New("unable to read ALPN extension data")
763752
}
764753
alpnProtocols = append(alpnProtocols, string(proto))
765754

766755
}
767-
e.SupportedProtocols = alpnProtocols
768-
return fullLen, nil
756+
return alpnProtocols, fullLen, nil
769757
}
770758

771-
// ApplicationSettingsExtensionNew represents the TLS ALPS codepoint extension introduced by Chrome 133.
772-
// More information can be found here: https://chromestatus.com/feature/5149147365900288
773-
// TODO: This probably should be implemented differently
774-
type ApplicationSettingsExtensionNew struct {
775-
*ApplicationSettingsExtension
759+
// ApplicationSettingsExtension embeds applicationSettingsExtension to implement the TLS ALPS extension on codepoint 17513
760+
type ApplicationSettingsExtension struct {
761+
applicationSettingsExtension
762+
SupportedProtocols []string
776763
}
777764

778-
func (e *ApplicationSettingsExtensionNew) Len() int {
779-
bLen := 2 + 2 + 2 // Type + Length + ALPS Extension length
780-
for _, s := range e.SupportedProtocols {
781-
bLen += 1 + len(s) // Supported ALPN Length + actual length of protocol
782-
}
783-
return bLen
765+
func (e *ApplicationSettingsExtension) Len() int {
766+
return e.applicationSettingsExtension.Len(e.SupportedProtocols)
784767
}
785768

786-
func (e *ApplicationSettingsExtensionNew) Read(b []byte) (int, error) {
787-
if len(b) < e.Len() {
788-
return 0, io.ErrShortBuffer
769+
func (e *ApplicationSettingsExtension) Read(b []byte) (int, error) {
770+
e.applicationSettingsExtension.codePoint = utlsExtensionApplicationSettings
771+
return e.applicationSettingsExtension.Read(b, e.SupportedProtocols)
772+
}
773+
774+
func (e *ApplicationSettingsExtension) UnmarshalJSON(b []byte) error {
775+
var applicationSettingsSupport struct {
776+
SupportedProtocols []string `json:"supported_protocols"`
789777
}
790778

791-
// Read Type.
792-
b[0] = byte(17613 >> 8) // hex: 44 dec: 68
793-
b[1] = byte(17613 & 0xff) // hex: 69 dec: 105
779+
if err := json.Unmarshal(b, &applicationSettingsSupport); err != nil {
780+
return err
781+
}
794782

795-
lengths := b[2:] // get the remaining buffer without Type
796-
b = b[6:] // set the buffer to the buffer without Type, Length and ALPS Extension Length (so only the Supported ALPN list remains)
783+
e.SupportedProtocols = applicationSettingsSupport.SupportedProtocols
784+
return nil
785+
}
797786

798-
stringsLength := 0
799-
for _, s := range e.SupportedProtocols {
800-
l := len(s) // Supported ALPN Length
801-
b[0] = byte(l) // Supported ALPN Length in bytes hex: 02 dec: 2
802-
copy(b[1:], s) // copy the Supported ALPN as bytes to the buffer
803-
b = b[1+l:] // set the buffer to the buffer without the Supported ALPN Length and Supported ALPN (so we can continue to the next protocol in this loop)
804-
stringsLength += 1 + l // Supported ALPN Length (the field itself) + Supported ALPN Length (the value)
805-
}
787+
// Write implementation copied from ALPNExtension.Write
788+
func (e *ApplicationSettingsExtension) Write(b []byte) (int, error) {
789+
var (
790+
fullLen int
791+
err error
792+
)
793+
e.SupportedProtocols, fullLen, err = e.applicationSettingsExtension.Write(b)
794+
return fullLen, err
795+
}
806796

807-
lengths[2] = byte(stringsLength >> 8) // ALPS Extension Length hex: 00 dec: 0
808-
lengths[3] = byte(stringsLength) // ALPS Extension Length hex: 03 dec: 3
809-
stringsLength += 2 // plus ALPS Extension Length field length
810-
lengths[0] = byte(stringsLength >> 8) // Length hex:00 dec: 0
811-
lengths[1] = byte(stringsLength) // Length hex: 05 dec: 5
797+
// ApplicationSettingsExtensionNew embeds applicationSettingsExtension to implement the TLS ALPS extension on codepoint 17613
798+
// More information can be found here: https://chromestatus.com/feature/5149147365900288
799+
type ApplicationSettingsExtensionNew struct {
800+
applicationSettingsExtension
801+
SupportedProtocols []string
802+
}
812803

813-
return e.Len(), io.EOF
804+
func (e *ApplicationSettingsExtensionNew) Len() int {
805+
return e.applicationSettingsExtension.Len(e.SupportedProtocols)
806+
}
807+
808+
func (e *ApplicationSettingsExtensionNew) Read(b []byte) (int, error) {
809+
e.applicationSettingsExtension.codePoint = utlsExtensionApplicationSettingsNew
810+
return e.applicationSettingsExtension.Read(b, e.SupportedProtocols)
814811
}
815812

816813
func (e *ApplicationSettingsExtensionNew) UnmarshalJSON(b []byte) error {
817814
var applicationSettingsSupport struct {
818-
SupportedProtocols []string `json:"supported_protocols_new"`
815+
SupportedProtocols []string `json:"supported_protocols"`
819816
}
820817

821818
if err := json.Unmarshal(b, &applicationSettingsSupport); err != nil {
@@ -828,24 +825,12 @@ func (e *ApplicationSettingsExtensionNew) UnmarshalJSON(b []byte) error {
828825

829826
// Write implementation copied from ALPNExtension.Write
830827
func (e *ApplicationSettingsExtensionNew) Write(b []byte) (int, error) {
831-
fullLen := len(b)
832-
extData := cryptobyte.String(b)
833-
// https://datatracker.ietf.org/doc/html/draft-vvv-tls-alps-01
834-
var protoList cryptobyte.String
835-
if !extData.ReadUint16LengthPrefixed(&protoList) || protoList.Empty() {
836-
return 0, errors.New("unable to read ALPN extension data")
837-
}
838-
alpnProtocols := []string{}
839-
for !protoList.Empty() {
840-
var proto cryptobyte.String
841-
if !protoList.ReadUint8LengthPrefixed(&proto) || proto.Empty() {
842-
return 0, errors.New("unable to read ALPN extension data")
843-
}
844-
alpnProtocols = append(alpnProtocols, string(proto))
845-
846-
}
847-
e.SupportedProtocols = alpnProtocols
848-
return fullLen, nil
828+
var (
829+
fullLen int
830+
err error
831+
)
832+
e.SupportedProtocols, fullLen, err = e.applicationSettingsExtension.Write(b)
833+
return fullLen, err
849834
}
850835

851836
// SCTExtension implements signed_certificate_timestamp (18)

0 commit comments

Comments
 (0)