Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 53 additions & 2 deletions tls/tls_handshake.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,13 @@ type ServerHello struct {
}

type SupportedVersionsExt struct {
SelectedVersion TLSVersion `json:"selected_version"`
SelectedVersion SelectedVersionExt `json:"selected_version"`
}

// SelectedVersionExt holds the TLSVersion and KeyExchange for TLSv1.3
type SelectedVersionExt struct {
Version TLSVersion `json:"-"`
KeyExchange *CurveID `json:"-"`
}

// SimpleCertificate holds a *x509.Certificate and a []byte for the certificate
Expand Down Expand Up @@ -178,6 +184,36 @@ func (v *TLSVersion) UnmarshalJSON(b []byte) error {
return nil
}

// MarshalJSON implements the json.Marshler interface
func (s SelectedVersionExt) MarshalJSON() ([]byte, error) {
aux := struct {
Name string `json:"name"`
Value int `json:"value"`
KeyExchange *CurveID `json:"key_exchange,omitempty"`
}{
Name: s.Version.String(),
Value: int(s.Version),
KeyExchange: s.KeyExchange,
}
return json.Marshal(&aux)
}

//UnmarshalJSON implements the json.Unmarshaler interface
func (s *SelectedVersionExt) UnmarshalJSON(data []byte) error {
aux := struct {
Name string `json:"name"`
Value int `json:"value"`
KeyExchange *CurveID `json:"key_exchange,omitempty"`
}{}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
s.Version = TLSVersion(aux.Value)
s.KeyExchange = aux.KeyExchange
return nil
}


// MarshalJSON implements the json.Marshler interface
func (cs *CipherSuiteID) MarshalJSON() ([]byte, error) {
buf := make([]byte, 2)
Expand Down Expand Up @@ -364,8 +400,23 @@ func (m *serverHelloMsg) MakeLog() *ServerHello {
sh.AlpnProtocol = m.alpnProtocol

if m.supportedVersion != 0 {
sv := SelectedVersionExt{
Version: TLSVersion(m.supportedVersion),
}

// TLS 1.3: negotiated key exchange group (supported group / CurveID).
// Preferred source: key_share in ServerHello (serverShare.group).
if m.serverShare.group != 0 {
g := m.serverShare.group
sv.KeyExchange = &g
} else if m.selectedGroup != 0 {
// HelloRetryRequest path: server selects a group but doesn't send a share yet.
g := m.selectedGroup
sv.KeyExchange = &g
}

sh.SupportedVersions = &SupportedVersionsExt{
SelectedVersion: TLSVersion(m.supportedVersion),
SelectedVersion: sv,
}
}

Expand Down
6 changes: 5 additions & 1 deletion zcrypto_schemas/zcrypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,11 @@ def getUnknowns(known, range, unknown="unknown"):
})

ServerSupportedVersions = SubRecordType({
"selected_version": TLSVersion(doc="The version of the TLS protocol selected by the server."),
"selected_version": SubRecordType({
"name": TLSVersionName(),
"value": Unsigned16BitInteger(doc="The TLS version identifier."),
"key_exchange": CurveID(doc="Negotiated TLS 1.3 key exchange group (NamedGroup/CurveID)."),
}, doc="The version of the TLS protocol selected by the server (TLS 1.3 may include negotiated key exchange group)."),
})

# tls/tls_handshake.go: type SessionTicket
Expand Down