ech_shared.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package tls
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "encoding/pem"
  6. E "github.com/sagernet/sing/common/exceptions"
  7. "github.com/cloudflare/circl/hpke"
  8. "github.com/cloudflare/circl/kem"
  9. )
  10. type ECHCapableConfig interface {
  11. Config
  12. ECHConfigList() []byte
  13. SetECHConfigList([]byte)
  14. }
  15. func ECHKeygenDefault(serverName string) (configPem string, keyPem string, err error) {
  16. cipherSuites := []echCipherSuite{
  17. {
  18. kdf: hpke.KDF_HKDF_SHA256,
  19. aead: hpke.AEAD_AES128GCM,
  20. }, {
  21. kdf: hpke.KDF_HKDF_SHA256,
  22. aead: hpke.AEAD_ChaCha20Poly1305,
  23. },
  24. }
  25. keyConfig := []myECHKeyConfig{
  26. {id: 0, kem: hpke.KEM_X25519_HKDF_SHA256},
  27. }
  28. keyPairs, err := echKeygen(0xfe0d, serverName, keyConfig, cipherSuites)
  29. if err != nil {
  30. return
  31. }
  32. var configBuffer bytes.Buffer
  33. var totalLen uint16
  34. for _, keyPair := range keyPairs {
  35. totalLen += uint16(len(keyPair.rawConf))
  36. }
  37. binary.Write(&configBuffer, binary.BigEndian, totalLen)
  38. for _, keyPair := range keyPairs {
  39. configBuffer.Write(keyPair.rawConf)
  40. }
  41. var keyBuffer bytes.Buffer
  42. for _, keyPair := range keyPairs {
  43. keyBuffer.Write(keyPair.rawKey)
  44. }
  45. configPem = string(pem.EncodeToMemory(&pem.Block{Type: "ECH CONFIGS", Bytes: configBuffer.Bytes()}))
  46. keyPem = string(pem.EncodeToMemory(&pem.Block{Type: "ECH KEYS", Bytes: keyBuffer.Bytes()}))
  47. return
  48. }
  49. type echKeyConfigPair struct {
  50. id uint8
  51. rawKey []byte
  52. conf myECHKeyConfig
  53. rawConf []byte
  54. }
  55. type echCipherSuite struct {
  56. kdf hpke.KDF
  57. aead hpke.AEAD
  58. }
  59. type myECHKeyConfig struct {
  60. id uint8
  61. kem hpke.KEM
  62. seed []byte
  63. }
  64. func echKeygen(version uint16, serverName string, conf []myECHKeyConfig, suite []echCipherSuite) ([]echKeyConfigPair, error) {
  65. be := binary.BigEndian
  66. // prepare for future update
  67. if version != 0xfe0d {
  68. return nil, E.New("unsupported ECH version", version)
  69. }
  70. suiteBuf := make([]byte, 0, len(suite)*4+2)
  71. suiteBuf = be.AppendUint16(suiteBuf, uint16(len(suite))*4)
  72. for _, s := range suite {
  73. if !s.kdf.IsValid() || !s.aead.IsValid() {
  74. return nil, E.New("invalid HPKE cipher suite")
  75. }
  76. suiteBuf = be.AppendUint16(suiteBuf, uint16(s.kdf))
  77. suiteBuf = be.AppendUint16(suiteBuf, uint16(s.aead))
  78. }
  79. pairs := []echKeyConfigPair{}
  80. for _, c := range conf {
  81. pair := echKeyConfigPair{}
  82. pair.id = c.id
  83. pair.conf = c
  84. if !c.kem.IsValid() {
  85. return nil, E.New("invalid HPKE KEM")
  86. }
  87. kpGenerator := c.kem.Scheme().GenerateKeyPair
  88. if len(c.seed) > 0 {
  89. kpGenerator = func() (kem.PublicKey, kem.PrivateKey, error) {
  90. pub, sec := c.kem.Scheme().DeriveKeyPair(c.seed)
  91. return pub, sec, nil
  92. }
  93. if len(c.seed) < c.kem.Scheme().PrivateKeySize() {
  94. return nil, E.New("HPKE KEM seed too short")
  95. }
  96. }
  97. pub, sec, err := kpGenerator()
  98. if err != nil {
  99. return nil, E.Cause(err, "generate ECH config key pair")
  100. }
  101. b := []byte{}
  102. b = be.AppendUint16(b, version)
  103. b = be.AppendUint16(b, 0) // length field
  104. // contents
  105. // key config
  106. b = append(b, c.id)
  107. b = be.AppendUint16(b, uint16(c.kem))
  108. pubBuf, err := pub.MarshalBinary()
  109. if err != nil {
  110. return nil, E.Cause(err, "serialize ECH public key")
  111. }
  112. b = be.AppendUint16(b, uint16(len(pubBuf)))
  113. b = append(b, pubBuf...)
  114. b = append(b, suiteBuf...)
  115. // end key config
  116. // max name len, not supported
  117. b = append(b, 0)
  118. // server name
  119. b = append(b, byte(len(serverName)))
  120. b = append(b, []byte(serverName)...)
  121. // extensions, not supported
  122. b = be.AppendUint16(b, 0)
  123. be.PutUint16(b[2:], uint16(len(b)-4))
  124. pair.rawConf = b
  125. secBuf, err := sec.MarshalBinary()
  126. if err != nil {
  127. return nil, E.Cause(err, "serialize ECH private key")
  128. }
  129. sk := []byte{}
  130. sk = be.AppendUint16(sk, uint16(len(secBuf)))
  131. sk = append(sk, secBuf...)
  132. sk = be.AppendUint16(sk, uint16(len(b)))
  133. sk = append(sk, b...)
  134. pair.rawKey = sk
  135. pairs = append(pairs, pair)
  136. }
  137. return pairs, nil
  138. }