| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 | 
							- package tls
 
- import (
 
- 	"bytes"
 
- 	"encoding/binary"
 
- 	"encoding/pem"
 
- 	E "github.com/sagernet/sing/common/exceptions"
 
- 	"github.com/cloudflare/circl/hpke"
 
- 	"github.com/cloudflare/circl/kem"
 
- )
 
- func ECHKeygenDefault(serverName string) (configPem string, keyPem string, err error) {
 
- 	cipherSuites := []echCipherSuite{
 
- 		{
 
- 			kdf:  hpke.KDF_HKDF_SHA256,
 
- 			aead: hpke.AEAD_AES128GCM,
 
- 		}, {
 
- 			kdf:  hpke.KDF_HKDF_SHA256,
 
- 			aead: hpke.AEAD_ChaCha20Poly1305,
 
- 		},
 
- 	}
 
- 	keyConfig := []myECHKeyConfig{
 
- 		{id: 0, kem: hpke.KEM_X25519_HKDF_SHA256},
 
- 	}
 
- 	keyPairs, err := echKeygen(0xfe0d, serverName, keyConfig, cipherSuites)
 
- 	if err != nil {
 
- 		return
 
- 	}
 
- 	var configBuffer bytes.Buffer
 
- 	var totalLen uint16
 
- 	for _, keyPair := range keyPairs {
 
- 		totalLen += uint16(len(keyPair.rawConf))
 
- 	}
 
- 	binary.Write(&configBuffer, binary.BigEndian, totalLen)
 
- 	for _, keyPair := range keyPairs {
 
- 		configBuffer.Write(keyPair.rawConf)
 
- 	}
 
- 	var keyBuffer bytes.Buffer
 
- 	for _, keyPair := range keyPairs {
 
- 		keyBuffer.Write(keyPair.rawKey)
 
- 	}
 
- 	configPem = string(pem.EncodeToMemory(&pem.Block{Type: "ECH CONFIGS", Bytes: configBuffer.Bytes()}))
 
- 	keyPem = string(pem.EncodeToMemory(&pem.Block{Type: "ECH KEYS", Bytes: keyBuffer.Bytes()}))
 
- 	return
 
- }
 
- type echKeyConfigPair struct {
 
- 	id      uint8
 
- 	rawKey  []byte
 
- 	conf    myECHKeyConfig
 
- 	rawConf []byte
 
- }
 
- type echCipherSuite struct {
 
- 	kdf  hpke.KDF
 
- 	aead hpke.AEAD
 
- }
 
- type myECHKeyConfig struct {
 
- 	id   uint8
 
- 	kem  hpke.KEM
 
- 	seed []byte
 
- }
 
- func echKeygen(version uint16, serverName string, conf []myECHKeyConfig, suite []echCipherSuite) ([]echKeyConfigPair, error) {
 
- 	be := binary.BigEndian
 
- 	// prepare for future update
 
- 	if version != 0xfe0d {
 
- 		return nil, E.New("unsupported ECH version", version)
 
- 	}
 
- 	suiteBuf := make([]byte, 0, len(suite)*4+2)
 
- 	suiteBuf = be.AppendUint16(suiteBuf, uint16(len(suite))*4)
 
- 	for _, s := range suite {
 
- 		if !s.kdf.IsValid() || !s.aead.IsValid() {
 
- 			return nil, E.New("invalid HPKE cipher suite")
 
- 		}
 
- 		suiteBuf = be.AppendUint16(suiteBuf, uint16(s.kdf))
 
- 		suiteBuf = be.AppendUint16(suiteBuf, uint16(s.aead))
 
- 	}
 
- 	pairs := []echKeyConfigPair{}
 
- 	for _, c := range conf {
 
- 		pair := echKeyConfigPair{}
 
- 		pair.id = c.id
 
- 		pair.conf = c
 
- 		if !c.kem.IsValid() {
 
- 			return nil, E.New("invalid HPKE KEM")
 
- 		}
 
- 		kpGenerator := c.kem.Scheme().GenerateKeyPair
 
- 		if len(c.seed) > 0 {
 
- 			kpGenerator = func() (kem.PublicKey, kem.PrivateKey, error) {
 
- 				pub, sec := c.kem.Scheme().DeriveKeyPair(c.seed)
 
- 				return pub, sec, nil
 
- 			}
 
- 			if len(c.seed) < c.kem.Scheme().PrivateKeySize() {
 
- 				return nil, E.New("HPKE KEM seed too short")
 
- 			}
 
- 		}
 
- 		pub, sec, err := kpGenerator()
 
- 		if err != nil {
 
- 			return nil, E.Cause(err, "generate ECH config key pair")
 
- 		}
 
- 		b := []byte{}
 
- 		b = be.AppendUint16(b, version)
 
- 		b = be.AppendUint16(b, 0) // length field
 
- 		// contents
 
- 		// key config
 
- 		b = append(b, c.id)
 
- 		b = be.AppendUint16(b, uint16(c.kem))
 
- 		pubBuf, err := pub.MarshalBinary()
 
- 		if err != nil {
 
- 			return nil, E.Cause(err, "serialize ECH public key")
 
- 		}
 
- 		b = be.AppendUint16(b, uint16(len(pubBuf)))
 
- 		b = append(b, pubBuf...)
 
- 		b = append(b, suiteBuf...)
 
- 		// end key config
 
- 		// max name len, not supported
 
- 		b = append(b, 0)
 
- 		// server name
 
- 		b = append(b, byte(len(serverName)))
 
- 		b = append(b, []byte(serverName)...)
 
- 		// extensions, not supported
 
- 		b = be.AppendUint16(b, 0)
 
- 		be.PutUint16(b[2:], uint16(len(b)-4))
 
- 		pair.rawConf = b
 
- 		secBuf, err := sec.MarshalBinary()
 
- 		if err != nil {
 
- 			return nil, E.Cause(err, "serialize ECH private key")
 
- 		}
 
- 		sk := []byte{}
 
- 		sk = be.AppendUint16(sk, uint16(len(secBuf)))
 
- 		sk = append(sk, secBuf...)
 
- 		sk = be.AppendUint16(sk, uint16(len(b)))
 
- 		sk = append(sk, b...)
 
- 		pair.rawKey = sk
 
- 		pairs = append(pairs, pair)
 
- 	}
 
- 	return pairs, nil
 
- }
 
 
  |