Unverified Commit b4de442d authored by Gaukas Wang's avatar Gaukas Wang Committed by GitHub
Browse files

feat: add GREASEEncryptedClientHelloExtension (#266)

* dicttls: update ECH-related entries

* wip: GREASE ECH extension

* new: GREASE ECH extension

* fix: GREASE ECH Read must succeed with io.EOF

* new: GREASE ECH multiple payload len

* new: parse ECH in EncryptedExtensions

* fix: ECHConfig Length always 0

* new: GREASE ECH parrots

* new: (*Config).ECHConfigs

Add (*Config).ECHConfigs for future full ECH extension.

* new: add GREASE ECH example

Add an incomplete example of using GREASE ECH extension (Chrome 120 parrot).

* fix: invalid httpGetOverConn call

fix a problem in old example where httpGetOverConn was called with uTlsConn.HandshakeState.ServerHello.AlpnProtocol, which will not be populated in case TLS 1.3 is used.

* new: possible InnerClientHello length
parent 9521fba9
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ const (
	alertUnknownPSKIdentity           alert = 115
	alertCertificateRequired          alert = 116
	alertNoApplicationProtocol        alert = 120
	alertECHRequired                  alert = 121
)

var alertText = map[alert]string{
@@ -94,6 +95,7 @@ var alertText = map[alert]string{
	alertUnknownPSKIdentity:           "unknown PSK identity",
	alertCertificateRequired:          "certificate required",
	alertNoApplicationProtocol:        "no application protocol",
	alertECHRequired:                  "ECH required",
}

func (e alert) String() string {
+17 −0
Original line number Diff line number Diff line
@@ -306,6 +306,11 @@ type ConnectionState struct {

	// ekm is a closure exposed via ExportKeyingMaterial.
	ekm func(label string, context []byte, length int) ([]byte, error)

	// ECHRetryConfigs contains the ECH retry configurations sent by the server in
	// EncryptedExtensions message. It is only populated if the server sent the
	// ech extension in EncryptedExtensions message.
	ECHRetryConfigs []ECHConfig // [uTLS]
}

// ExportKeyingMaterial returns length bytes of exported key material in a new
@@ -836,6 +841,17 @@ type Config struct {
	// autoSessionTicketKeys is like sessionTicketKeys but is owned by the
	// auto-rotation logic. See Config.ticketKeys.
	autoSessionTicketKeys []ticketKey

	// ECHConfigs contains the ECH configurations to be used by the ECH
	// extension if any.
	// It could either be distributed by the server in EncryptedExtensions
	// message or out-of-band.
	//
	// If ECHConfigs is nil and an ECH extension is present, GREASEd ECH
	// extension will be sent.
	//
	// If GREASE ECH extension is present, this field will be ignored.
	ECHConfigs []ECHConfig // [uTLS]
}

const (
@@ -921,6 +937,7 @@ func (c *Config) Clone() *Config {
		autoSessionTicketKeys:       c.autoSessionTicketKeys,

		PreferSkipResumptionOnNilExtension: c.PreferSkipResumptionOnNilExtension, // [UTLS]
		ECHConfigs:                         c.ECHConfigs,                         // [uTLS]
	}
}

+19 −0
Original line number Diff line number Diff line
package dicttls

// source: https://www.iana.org/assignments/hpke/hpke.xhtml
// last updated: December 2023

const (
	AEAD_AES_128_GCM       uint16 = 0x0001 // NIST Special Publication 800-38D
	AEAD_AES_256_GCM       uint16 = 0x0002 // NIST Special Publication 800-38D
	AEAD_CHACHA20_POLY1305 uint16 = 0x0003 // RFC 8439
	AEAD_EXPORT_ONLY       uint16 = 0xFFFF // RFC 9180
)

var DictAEADIdentifierValueIndexed = map[uint16]string{
	0x0000: "Reserved", // RFC 9180
	0x0001: "AES-128-GCM",
	0x0002: "AES-256-GCM",
	0x0003: "ChaCha20Poly1305",
	0xFFFF: "Export-only", // RFC 9180
}
+7 −2
Original line number Diff line number Diff line
package dicttls

// source: https://www.iana.org/assignments/tls-parameters/tls-kdf-ids.csv
// last updated: March 2023
// source: https://www.iana.org/assignments/hpke/hpke.xhtml
// last updated: December 2023

const (
	HKDF_SHA256 uint16 = 0x0001
	HKDF_SHA384 uint16 = 0x0002
	HKDF_SHA512 uint16 = 0x0003
)

var DictKDFIdentifierValueIndexed = map[uint16]string{
	0x0000: "Reserved", // RFC 9180
	0x0001: "HKDF_SHA256",
	0x0002: "HKDF_SHA384",
	0x0003: "HKDF_SHA512",
}

var DictKDFIdentifierNameIndexed = map[string]uint16{
	"Reserved":    0x0000, // RFC 9180
	"HKDF_SHA256": 0x0001,
	"HKDF_SHA384": 0x0002,
	"HKDF_SHA512": 0x0003,
}
+53 −0
Original line number Diff line number Diff line
package dicttls

// source: https://www.iana.org/assignments/hpke/hpke.xhtml
// last updated: December 2023

const (
	DHKEM_P256_HKDF_SHA256      uint16 = 0x0010 // RFC 5869
	DHKEM_P384_HKDF_SHA384      uint16 = 0x0011 // RFC 5869
	DHKEM_P521_HKDF_SHA512      uint16 = 0x0012 // RFC 5869
	DHKEM_CP256_HKDF_SHA256     uint16 = 0x0013 // RFC 6090
	DHKEM_CP384_HKDF_SHA384     uint16 = 0x0014 // RFC 6090
	DHKEM_CP521_HKDF_SHA512     uint16 = 0x0015 // RFC 6090
	DHKEM_SECP256K1_HKDF_SHA256 uint16 = 0x0016 // draft-wahby-cfrg-hpke-kem-secp256k1-01

	DHKEM_X25519_HKDF_SHA256 uint16 = 0x0020 // RFC 7748
	DHKEM_X448_HKDF_SHA512   uint16 = 0x0021 // RFC 7748

	X25519_KYBER768_DRAFT00 uint16 = 0x0030 // draft-westerbaan-cfrg-hpke-xyber768d00-02
)

var DictKEMIdentifierValueIndexed = map[uint16]string{
	0x0000: "Reserved", // RFC 9180

	0x0010: "DHKEM(P-256, HKDF-SHA256)",
	0x0011: "DHKEM(P-384, HKDF-SHA384)",
	0x0012: "DHKEM(P-521, HKDF-SHA512)",
	0x0013: "DHKEM(CP-256, HKDF-SHA256)",
	0x0014: "DHKEM(CP-384, HKDF-SHA384)",
	0x0015: "DHKEM(CP-521, HKDF-SHA512)",
	0x0016: "DHKEM(secp256k1, HKDF-SHA256)",

	0x0020: "DHKEM(X25519, HKDF-SHA256)",
	0x0021: "DHKEM(X448, HKDF-SHA512)",

	0x0030: "X25519Kyber768Draft00",
}

var DictKEMIdentifierNameIndexed = map[string]uint16{
	"Reserved": 0x0000, // RFC 9180

	"DHKEM(P-256, HKDF-SHA256)":     0x0010,
	"DHKEM(P-384, HKDF-SHA384)":     0x0011,
	"DHKEM(P-521, HKDF-SHA512)":     0x0012,
	"DHKEM(CP-256, HKDF-SHA256)":    0x0013,
	"DHKEM(CP-384, HKDF-SHA384)":    0x0014,
	"DHKEM(CP-521, HKDF-SHA512)":    0x0015,
	"DHKEM(secp256k1, HKDF-SHA256)": 0x0016,

	"DHKEM(X25519, HKDF-SHA256)": 0x0020,
	"DHKEM(X448, HKDF-SHA512)":   0x0021,

	"X25519Kyber768Draft00": 0x0030,
}
Loading