ech.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. // Copyright 2024 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package tls
  5. import (
  6. "errors"
  7. "strings"
  8. "github.com/Psiphon-Labs/utls/internal/hpke"
  9. "golang.org/x/crypto/cryptobyte"
  10. )
  11. type echCipher struct {
  12. KDFID uint16
  13. AEADID uint16
  14. }
  15. type echExtension struct {
  16. Type uint16
  17. Data []byte
  18. }
  19. type echConfig struct {
  20. raw []byte
  21. Version uint16
  22. Length uint16
  23. ConfigID uint8
  24. KemID uint16
  25. PublicKey []byte
  26. SymmetricCipherSuite []echCipher
  27. MaxNameLength uint8
  28. PublicName []byte
  29. Extensions []echExtension
  30. }
  31. var errMalformedECHConfig = errors.New("tls: malformed ECHConfigList")
  32. // parseECHConfigList parses a draft-ietf-tls-esni-18 ECHConfigList, returning a
  33. // slice of parsed ECHConfigs, in the same order they were parsed, or an error
  34. // if the list is malformed.
  35. func parseECHConfigList(data []byte) ([]echConfig, error) {
  36. s := cryptobyte.String(data)
  37. // Skip the length prefix
  38. var length uint16
  39. if !s.ReadUint16(&length) {
  40. return nil, errMalformedECHConfig
  41. }
  42. if length != uint16(len(data)-2) {
  43. return nil, errMalformedECHConfig
  44. }
  45. var configs []echConfig
  46. for len(s) > 0 {
  47. var ec echConfig
  48. ec.raw = []byte(s)
  49. if !s.ReadUint16(&ec.Version) {
  50. return nil, errMalformedECHConfig
  51. }
  52. if !s.ReadUint16(&ec.Length) {
  53. return nil, errMalformedECHConfig
  54. }
  55. if len(ec.raw) < int(ec.Length)+4 {
  56. return nil, errMalformedECHConfig
  57. }
  58. ec.raw = ec.raw[:ec.Length+4]
  59. if ec.Version != extensionEncryptedClientHello {
  60. s.Skip(int(ec.Length))
  61. continue
  62. }
  63. if !s.ReadUint8(&ec.ConfigID) {
  64. return nil, errMalformedECHConfig
  65. }
  66. if !s.ReadUint16(&ec.KemID) {
  67. return nil, errMalformedECHConfig
  68. }
  69. if !s.ReadUint16LengthPrefixed((*cryptobyte.String)(&ec.PublicKey)) {
  70. return nil, errMalformedECHConfig
  71. }
  72. var cipherSuites cryptobyte.String
  73. if !s.ReadUint16LengthPrefixed(&cipherSuites) {
  74. return nil, errMalformedECHConfig
  75. }
  76. for !cipherSuites.Empty() {
  77. var c echCipher
  78. if !cipherSuites.ReadUint16(&c.KDFID) {
  79. return nil, errMalformedECHConfig
  80. }
  81. if !cipherSuites.ReadUint16(&c.AEADID) {
  82. return nil, errMalformedECHConfig
  83. }
  84. ec.SymmetricCipherSuite = append(ec.SymmetricCipherSuite, c)
  85. }
  86. if !s.ReadUint8(&ec.MaxNameLength) {
  87. return nil, errMalformedECHConfig
  88. }
  89. var publicName cryptobyte.String
  90. if !s.ReadUint8LengthPrefixed(&publicName) {
  91. return nil, errMalformedECHConfig
  92. }
  93. ec.PublicName = publicName
  94. var extensions cryptobyte.String
  95. if !s.ReadUint16LengthPrefixed(&extensions) {
  96. return nil, errMalformedECHConfig
  97. }
  98. for !extensions.Empty() {
  99. var e echExtension
  100. if !extensions.ReadUint16(&e.Type) {
  101. return nil, errMalformedECHConfig
  102. }
  103. if !extensions.ReadUint16LengthPrefixed((*cryptobyte.String)(&e.Data)) {
  104. return nil, errMalformedECHConfig
  105. }
  106. ec.Extensions = append(ec.Extensions, e)
  107. }
  108. configs = append(configs, ec)
  109. }
  110. return configs, nil
  111. }
  112. func pickECHConfig(list []echConfig) *echConfig {
  113. for _, ec := range list {
  114. if _, ok := hpke.SupportedKEMs[ec.KemID]; !ok {
  115. continue
  116. }
  117. var validSCS bool
  118. for _, cs := range ec.SymmetricCipherSuite {
  119. if _, ok := hpke.SupportedAEADs[cs.AEADID]; !ok {
  120. continue
  121. }
  122. if _, ok := hpke.SupportedKDFs[cs.KDFID]; !ok {
  123. continue
  124. }
  125. validSCS = true
  126. break
  127. }
  128. if !validSCS {
  129. continue
  130. }
  131. if !validDNSName(string(ec.PublicName)) {
  132. continue
  133. }
  134. var unsupportedExt bool
  135. for _, ext := range ec.Extensions {
  136. // If high order bit is set to 1 the extension is mandatory.
  137. // Since we don't support any extensions, if we see a mandatory
  138. // bit, we skip the config.
  139. if ext.Type&uint16(1<<15) != 0 {
  140. unsupportedExt = true
  141. }
  142. }
  143. if unsupportedExt {
  144. continue
  145. }
  146. return &ec
  147. }
  148. return nil
  149. }
  150. func pickECHCipherSuite(suites []echCipher) (echCipher, error) {
  151. for _, s := range suites {
  152. // NOTE: all of the supported AEADs and KDFs are fine, rather than
  153. // imposing some sort of preference here, we just pick the first valid
  154. // suite.
  155. if _, ok := hpke.SupportedAEADs[s.AEADID]; !ok {
  156. continue
  157. }
  158. if _, ok := hpke.SupportedKDFs[s.KDFID]; !ok {
  159. continue
  160. }
  161. return s, nil
  162. }
  163. return echCipher{}, errors.New("tls: no supported symmetric ciphersuites for ECH")
  164. }
  165. func encodeInnerClientHello(inner *clientHelloMsg, maxNameLength int) ([]byte, error) {
  166. h, err := inner.marshalMsg(true)
  167. if err != nil {
  168. return nil, err
  169. }
  170. h = h[4:] // strip four byte prefix
  171. var paddingLen int
  172. if inner.serverName != "" {
  173. paddingLen = max(0, maxNameLength-len(inner.serverName))
  174. } else {
  175. paddingLen = maxNameLength + 9
  176. }
  177. paddingLen = 31 - ((len(h) + paddingLen - 1) % 32)
  178. return append(h, make([]byte, paddingLen)...), nil
  179. }
  180. func generateOuterECHExt(id uint8, kdfID, aeadID uint16, encodedKey []byte, payload []byte) ([]byte, error) {
  181. var b cryptobyte.Builder
  182. b.AddUint8(0) // outer
  183. b.AddUint16(kdfID)
  184. b.AddUint16(aeadID)
  185. b.AddUint8(id)
  186. b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { b.AddBytes(encodedKey) })
  187. b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { b.AddBytes(payload) })
  188. return b.Bytes()
  189. }
  190. func computeAndUpdateOuterECHExtension(outer, inner *clientHelloMsg, ech *echContext, useKey bool) error {
  191. var encapKey []byte
  192. if useKey {
  193. encapKey = ech.encapsulatedKey
  194. }
  195. encodedInner, err := encodeInnerClientHello(inner, int(ech.config.MaxNameLength))
  196. if err != nil {
  197. return err
  198. }
  199. // NOTE: the tag lengths for all of the supported AEADs are the same (16
  200. // bytes), so we have hardcoded it here. If we add support for another AEAD
  201. // with a different tag length, we will need to change this.
  202. encryptedLen := len(encodedInner) + 16 // AEAD tag length
  203. outer.encryptedClientHello, err = generateOuterECHExt(ech.config.ConfigID, ech.kdfID, ech.aeadID, encapKey, make([]byte, encryptedLen))
  204. if err != nil {
  205. return err
  206. }
  207. serializedOuter, err := outer.marshal()
  208. if err != nil {
  209. return err
  210. }
  211. serializedOuter = serializedOuter[4:] // strip the four byte prefix
  212. encryptedInner, err := ech.hpkeContext.Seal(serializedOuter, encodedInner)
  213. if err != nil {
  214. return err
  215. }
  216. outer.encryptedClientHello, err = generateOuterECHExt(ech.config.ConfigID, ech.kdfID, ech.aeadID, encapKey, encryptedInner)
  217. if err != nil {
  218. return err
  219. }
  220. return nil
  221. }
  222. // validDNSName is a rather rudimentary check for the validity of a DNS name.
  223. // This is used to check if the public_name in a ECHConfig is valid when we are
  224. // picking a config. This can be somewhat lax because even if we pick a
  225. // valid-looking name, the DNS layer will later reject it anyway.
  226. func validDNSName(name string) bool {
  227. if len(name) > 253 {
  228. return false
  229. }
  230. labels := strings.Split(name, ".")
  231. if len(labels) <= 1 {
  232. return false
  233. }
  234. for _, l := range labels {
  235. labelLen := len(l)
  236. if labelLen == 0 {
  237. return false
  238. }
  239. for i, r := range l {
  240. if r == '-' && (i == 0 || i == labelLen-1) {
  241. return false
  242. }
  243. if (r < '0' || r > '9') && (r < 'a' || r > 'z') && (r < 'A' || r > 'Z') && r != '-' {
  244. return false
  245. }
  246. }
  247. }
  248. return true
  249. }
  250. // ECHRejectionError is the error type returned when ECH is rejected by a remote
  251. // server. If the server offered a ECHConfigList to use for retries, the
  252. // RetryConfigList field will contain this list.
  253. //
  254. // The client may treat an ECHRejectionError with an empty set of RetryConfigs
  255. // as a secure signal from the server.
  256. type ECHRejectionError struct {
  257. RetryConfigList []byte
  258. }
  259. func (e *ECHRejectionError) Error() string {
  260. return "tls: server rejected ECH"
  261. }