1
2
3
4
5 package tls
6
7 import (
8 "bytes"
9 "crypto/hpke"
10 "errors"
11 "fmt"
12 "strings"
13
14 "golang.org/x/crypto/cryptobyte"
15 )
16
17 type echCipher struct {
18 KDFID uint16
19 AEADID uint16
20 }
21
22 type echExtension struct {
23 Type uint16
24 Data []byte
25 }
26
27 type echConfig struct {
28 raw []byte
29
30 Version uint16
31 Length uint16
32
33 ConfigID uint8
34 KemID uint16
35 PublicKey []byte
36 SymmetricCipherSuite []echCipher
37
38 MaxNameLength uint8
39 PublicName []byte
40 Extensions []echExtension
41 }
42
43 var errMalformedECHConfigList = errors.New("tls: malformed ECHConfigList")
44
45 type echConfigErr struct {
46 field string
47 }
48
49 func (e *echConfigErr) Error() string {
50 if e.field == "" {
51 return "tls: malformed ECHConfig"
52 }
53 return fmt.Sprintf("tls: malformed ECHConfig, invalid %s field", e.field)
54 }
55
56 func parseECHConfig(enc []byte) (skip bool, ec echConfig, err error) {
57 s := cryptobyte.String(enc)
58 ec.raw = []byte(enc)
59 if !s.ReadUint16(&ec.Version) {
60 return false, echConfig{}, &echConfigErr{"version"}
61 }
62 if !s.ReadUint16(&ec.Length) {
63 return false, echConfig{}, &echConfigErr{"length"}
64 }
65 if len(ec.raw) < int(ec.Length)+4 {
66 return false, echConfig{}, &echConfigErr{"length"}
67 }
68 ec.raw = ec.raw[:ec.Length+4]
69 if ec.Version != extensionEncryptedClientHello {
70 s.Skip(int(ec.Length))
71 return true, echConfig{}, nil
72 }
73 if !s.ReadUint8(&ec.ConfigID) {
74 return false, echConfig{}, &echConfigErr{"config_id"}
75 }
76 if !s.ReadUint16(&ec.KemID) {
77 return false, echConfig{}, &echConfigErr{"kem_id"}
78 }
79 if !readUint16LengthPrefixed(&s, &ec.PublicKey) {
80 return false, echConfig{}, &echConfigErr{"public_key"}
81 }
82 var cipherSuites cryptobyte.String
83 if !s.ReadUint16LengthPrefixed(&cipherSuites) {
84 return false, echConfig{}, &echConfigErr{"cipher_suites"}
85 }
86 for !cipherSuites.Empty() {
87 var c echCipher
88 if !cipherSuites.ReadUint16(&c.KDFID) {
89 return false, echConfig{}, &echConfigErr{"cipher_suites kdf_id"}
90 }
91 if !cipherSuites.ReadUint16(&c.AEADID) {
92 return false, echConfig{}, &echConfigErr{"cipher_suites aead_id"}
93 }
94 ec.SymmetricCipherSuite = append(ec.SymmetricCipherSuite, c)
95 }
96 if !s.ReadUint8(&ec.MaxNameLength) {
97 return false, echConfig{}, &echConfigErr{"maximum_name_length"}
98 }
99 var publicName cryptobyte.String
100 if !s.ReadUint8LengthPrefixed(&publicName) {
101 return false, echConfig{}, &echConfigErr{"public_name"}
102 }
103 ec.PublicName = publicName
104 var extensions cryptobyte.String
105 if !s.ReadUint16LengthPrefixed(&extensions) {
106 return false, echConfig{}, &echConfigErr{"extensions"}
107 }
108 for !extensions.Empty() {
109 var e echExtension
110 if !extensions.ReadUint16(&e.Type) {
111 return false, echConfig{}, &echConfigErr{"extensions type"}
112 }
113 if !extensions.ReadUint16LengthPrefixed((*cryptobyte.String)(&e.Data)) {
114 return false, echConfig{}, &echConfigErr{"extensions data"}
115 }
116 ec.Extensions = append(ec.Extensions, e)
117 }
118
119 return false, ec, nil
120 }
121
122
123
124
125 func parseECHConfigList(data []byte) ([]echConfig, error) {
126 s := cryptobyte.String(data)
127 var length uint16
128 if !s.ReadUint16(&length) {
129 return nil, errMalformedECHConfigList
130 }
131 if length != uint16(len(data)-2) {
132 return nil, errMalformedECHConfigList
133 }
134 var configs []echConfig
135 for len(s) > 0 {
136 if len(s) < 4 {
137 return nil, errors.New("tls: malformed ECHConfig")
138 }
139 configLen := uint16(s[2])<<8 | uint16(s[3])
140 skip, ec, err := parseECHConfig(s)
141 if err != nil {
142 return nil, err
143 }
144 s = s[configLen+4:]
145 if !skip {
146 configs = append(configs, ec)
147 }
148 }
149 return configs, nil
150 }
151
152 func pickECHConfig(list []echConfig) (*echConfig, hpke.PublicKey, hpke.KDF, hpke.AEAD) {
153 for _, ec := range list {
154 if !validDNSName(string(ec.PublicName)) {
155 continue
156 }
157 var unsupportedExt bool
158 for _, ext := range ec.Extensions {
159
160
161
162 if ext.Type&uint16(1<<15) != 0 {
163 unsupportedExt = true
164 }
165 }
166 if unsupportedExt {
167 continue
168 }
169 kem, err := hpke.NewKEM(ec.KemID)
170 if err != nil {
171 continue
172 }
173 pub, err := kem.NewPublicKey(ec.PublicKey)
174 if err != nil {
175
176
177 continue
178 }
179 for _, cs := range ec.SymmetricCipherSuite {
180
181
182
183 kdf, err := hpke.NewKDF(cs.KDFID)
184 if err != nil {
185 continue
186 }
187
188
189 if cs.AEADID == 0xFFFF {
190 continue
191 }
192 aead, err := hpke.NewAEAD(cs.AEADID)
193 if err != nil {
194 continue
195 }
196 return &ec, pub, kdf, aead
197 }
198 }
199 return nil, nil, nil, nil
200 }
201
202 func encodeInnerClientHello(inner *clientHelloMsg, maxNameLength int) ([]byte, error) {
203 h, err := inner.marshalMsg(true)
204 if err != nil {
205 return nil, err
206 }
207 h = h[4:]
208
209 var paddingLen int
210 if inner.serverName != "" {
211 paddingLen = max(0, maxNameLength-len(inner.serverName))
212 } else {
213 paddingLen = maxNameLength + 9
214 }
215 paddingLen += 31 - ((len(h) + paddingLen - 1) % 32)
216
217 return append(h, make([]byte, paddingLen)...), nil
218 }
219
220 func skipUint8LengthPrefixed(s *cryptobyte.String) bool {
221 var skip uint8
222 if !s.ReadUint8(&skip) {
223 return false
224 }
225 return s.Skip(int(skip))
226 }
227
228 func skipUint16LengthPrefixed(s *cryptobyte.String) bool {
229 var skip uint16
230 if !s.ReadUint16(&skip) {
231 return false
232 }
233 return s.Skip(int(skip))
234 }
235
236 type rawExtension struct {
237 extType uint16
238 data []byte
239 }
240
241 func extractRawExtensions(hello *clientHelloMsg) ([]rawExtension, error) {
242 s := cryptobyte.String(hello.original)
243 if !s.Skip(4+2+32) ||
244 !skipUint8LengthPrefixed(&s) ||
245 !skipUint16LengthPrefixed(&s) ||
246 !skipUint8LengthPrefixed(&s) {
247 return nil, errors.New("tls: malformed outer client hello")
248 }
249 var rawExtensions []rawExtension
250 var extensions cryptobyte.String
251 if !s.ReadUint16LengthPrefixed(&extensions) {
252 return nil, errors.New("tls: malformed outer client hello")
253 }
254
255 for !extensions.Empty() {
256 var extension uint16
257 var extData cryptobyte.String
258 if !extensions.ReadUint16(&extension) ||
259 !extensions.ReadUint16LengthPrefixed(&extData) {
260 return nil, errors.New("tls: invalid inner client hello")
261 }
262 rawExtensions = append(rawExtensions, rawExtension{extension, extData})
263 }
264 return rawExtensions, nil
265 }
266
267 func decodeInnerClientHello(outer *clientHelloMsg, encoded []byte) (*clientHelloMsg, error) {
268
269
270
271
272
273
274
275
276 innerReader := cryptobyte.String(encoded)
277 var versionAndRandom, sessionID, cipherSuites, compressionMethods []byte
278 var extensions cryptobyte.String
279 if !innerReader.ReadBytes(&versionAndRandom, 2+32) ||
280 !readUint8LengthPrefixed(&innerReader, &sessionID) ||
281 len(sessionID) != 0 ||
282 !readUint16LengthPrefixed(&innerReader, &cipherSuites) ||
283 !readUint8LengthPrefixed(&innerReader, &compressionMethods) ||
284 !innerReader.ReadUint16LengthPrefixed(&extensions) {
285 return nil, errors.New("tls: invalid inner client hello")
286 }
287
288
289
290
291 for _, p := range innerReader {
292 if p != 0 {
293 return nil, errors.New("tls: invalid inner client hello")
294 }
295 }
296
297 rawOuterExts, err := extractRawExtensions(outer)
298 if err != nil {
299 return nil, err
300 }
301
302 recon := cryptobyte.NewBuilder(nil)
303 recon.AddUint8(typeClientHello)
304 recon.AddUint24LengthPrefixed(func(recon *cryptobyte.Builder) {
305 recon.AddBytes(versionAndRandom)
306 recon.AddUint8LengthPrefixed(func(recon *cryptobyte.Builder) {
307 recon.AddBytes(outer.sessionId)
308 })
309 recon.AddUint16LengthPrefixed(func(recon *cryptobyte.Builder) {
310 recon.AddBytes(cipherSuites)
311 })
312 recon.AddUint8LengthPrefixed(func(recon *cryptobyte.Builder) {
313 recon.AddBytes(compressionMethods)
314 })
315 recon.AddUint16LengthPrefixed(func(recon *cryptobyte.Builder) {
316 for !extensions.Empty() {
317 var extension uint16
318 var extData cryptobyte.String
319 if !extensions.ReadUint16(&extension) ||
320 !extensions.ReadUint16LengthPrefixed(&extData) {
321 recon.SetError(errors.New("tls: invalid inner client hello"))
322 return
323 }
324 if extension == extensionECHOuterExtensions {
325 if !extData.ReadUint8LengthPrefixed(&extData) {
326 recon.SetError(errors.New("tls: invalid inner client hello"))
327 return
328 }
329 var i int
330 for !extData.Empty() {
331 var extType uint16
332 if !extData.ReadUint16(&extType) {
333 recon.SetError(errors.New("tls: invalid inner client hello"))
334 return
335 }
336 if extType == extensionEncryptedClientHello {
337 recon.SetError(errors.New("tls: invalid outer extensions"))
338 return
339 }
340 for ; i <= len(rawOuterExts); i++ {
341 if i == len(rawOuterExts) {
342 recon.SetError(errors.New("tls: invalid outer extensions"))
343 return
344 }
345 if rawOuterExts[i].extType == extType {
346 break
347 }
348 }
349 recon.AddUint16(rawOuterExts[i].extType)
350 recon.AddUint16LengthPrefixed(func(recon *cryptobyte.Builder) {
351 recon.AddBytes(rawOuterExts[i].data)
352 })
353 }
354 } else {
355 recon.AddUint16(extension)
356 recon.AddUint16LengthPrefixed(func(recon *cryptobyte.Builder) {
357 recon.AddBytes(extData)
358 })
359 }
360 }
361 })
362 })
363
364 reconBytes, err := recon.Bytes()
365 if err != nil {
366 return nil, err
367 }
368 inner := &clientHelloMsg{}
369 if !inner.unmarshal(reconBytes) {
370 return nil, errors.New("tls: invalid reconstructed inner client hello")
371 }
372
373 if !bytes.Equal(inner.encryptedClientHello, []byte{uint8(innerECHExt)}) {
374 return nil, errInvalidECHExt
375 }
376
377 hasTLS13 := false
378 for _, v := range inner.supportedVersions {
379
380
381
382
383
384 if v&0x0F0F == 0x0A0A && v&0xff == v>>8 {
385 continue
386 }
387
388
389 if v == VersionTLS13 {
390 hasTLS13 = true
391 } else if v < VersionTLS13 {
392
393 return nil, errors.New("tls: client sent encrypted_client_hello extension with unsupported versions")
394 }
395 }
396
397 if !hasTLS13 {
398 return nil, errors.New("tls: client sent encrypted_client_hello extension but did not offer TLS 1.3")
399 }
400
401 return inner, nil
402 }
403
404 func decryptECHPayload(context *hpke.Recipient, hello, payload []byte) ([]byte, error) {
405 outerAAD := bytes.Replace(hello[4:], payload, make([]byte, len(payload)), 1)
406 return context.Open(outerAAD, payload)
407 }
408
409 func generateOuterECHExt(id uint8, kdfID, aeadID uint16, encodedKey []byte, payload []byte) ([]byte, error) {
410 var b cryptobyte.Builder
411 b.AddUint8(0)
412 b.AddUint16(kdfID)
413 b.AddUint16(aeadID)
414 b.AddUint8(id)
415 b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { b.AddBytes(encodedKey) })
416 b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { b.AddBytes(payload) })
417 return b.Bytes()
418 }
419
420 func computeAndUpdateOuterECHExtension(outer, inner *clientHelloMsg, ech *echClientContext, useKey bool) error {
421 var encapKey []byte
422 if useKey {
423 encapKey = ech.encapsulatedKey
424 }
425 encodedInner, err := encodeInnerClientHello(inner, int(ech.config.MaxNameLength))
426 if err != nil {
427 return err
428 }
429
430
431
432 encryptedLen := len(encodedInner) + 16
433 outer.encryptedClientHello, err = generateOuterECHExt(ech.config.ConfigID, ech.kdfID, ech.aeadID, encapKey, make([]byte, encryptedLen))
434 if err != nil {
435 return err
436 }
437 serializedOuter, err := outer.marshal()
438 if err != nil {
439 return err
440 }
441 serializedOuter = serializedOuter[4:]
442 encryptedInner, err := ech.hpkeContext.Seal(serializedOuter, encodedInner)
443 if err != nil {
444 return err
445 }
446 outer.encryptedClientHello, err = generateOuterECHExt(ech.config.ConfigID, ech.kdfID, ech.aeadID, encapKey, encryptedInner)
447 if err != nil {
448 return err
449 }
450 return nil
451 }
452
453
454
455
456
457 func validDNSName(name string) bool {
458 if len(name) > 253 {
459 return false
460 }
461 labels := strings.Split(name, ".")
462 if len(labels) <= 1 {
463 return false
464 }
465 for _, l := range labels {
466 labelLen := len(l)
467 if labelLen == 0 {
468 return false
469 }
470 for i, r := range l {
471 if r == '-' && (i == 0 || i == labelLen-1) {
472 return false
473 }
474 if (r < '0' || r > '9') && (r < 'a' || r > 'z') && (r < 'A' || r > 'Z') && r != '-' {
475 return false
476 }
477 }
478 }
479 return true
480 }
481
482
483
484
485
486
487
488 type ECHRejectionError struct {
489 RetryConfigList []byte
490 }
491
492 func (e *ECHRejectionError) Error() string {
493 return "tls: server rejected ECH"
494 }
495
496 var errMalformedECHExt = errors.New("tls: malformed encrypted_client_hello extension")
497 var errInvalidECHExt = errors.New("tls: client sent invalid encrypted_client_hello extension")
498
499 type echExtType uint8
500
501 const (
502 innerECHExt echExtType = 1
503 outerECHExt echExtType = 0
504 )
505
506 func parseECHExt(ext []byte) (echType echExtType, cs echCipher, configID uint8, encap []byte, payload []byte, err error) {
507 data := make([]byte, len(ext))
508 copy(data, ext)
509 s := cryptobyte.String(data)
510 var echInt uint8
511 if !s.ReadUint8(&echInt) {
512 err = errMalformedECHExt
513 return
514 }
515 echType = echExtType(echInt)
516 if echType == innerECHExt {
517 if !s.Empty() {
518 err = errMalformedECHExt
519 return
520 }
521 return echType, cs, 0, nil, nil, nil
522 }
523 if echType != outerECHExt {
524 err = errInvalidECHExt
525 return
526 }
527 if !s.ReadUint16(&cs.KDFID) {
528 err = errMalformedECHExt
529 return
530 }
531 if !s.ReadUint16(&cs.AEADID) {
532 err = errMalformedECHExt
533 return
534 }
535 if !s.ReadUint8(&configID) {
536 err = errMalformedECHExt
537 return
538 }
539 if !readUint16LengthPrefixed(&s, &encap) {
540 err = errMalformedECHExt
541 return
542 }
543 if !readUint16LengthPrefixed(&s, &payload) {
544 err = errMalformedECHExt
545 return
546 }
547
548
549
550 return echType, cs, configID, bytes.Clone(encap), bytes.Clone(payload), nil
551 }
552
553 func (c *Conn) processECHClientHello(outer *clientHelloMsg, echKeys []EncryptedClientHelloKey) (*clientHelloMsg, *echServerContext, error) {
554 echType, echCiphersuite, configID, encap, payload, err := parseECHExt(outer.encryptedClientHello)
555 if err != nil {
556 if errors.Is(err, errInvalidECHExt) {
557 c.sendAlert(alertIllegalParameter)
558 } else {
559 c.sendAlert(alertDecodeError)
560 }
561
562 return nil, nil, errInvalidECHExt
563 }
564
565 if echType == innerECHExt {
566 return outer, &echServerContext{inner: true}, nil
567 }
568
569 if len(echKeys) == 0 {
570 return outer, nil, nil
571 }
572
573 for _, echKey := range echKeys {
574 skip, config, err := parseECHConfig(echKey.Config)
575 if err != nil {
576 c.sendAlert(alertInternalError)
577 return nil, nil, fmt.Errorf("tls: invalid EncryptedClientHelloKey Config: %s", err)
578 }
579 if skip {
580 continue
581 }
582 kem, err := hpke.NewKEM(config.KemID)
583 if err != nil {
584 c.sendAlert(alertInternalError)
585 return nil, nil, fmt.Errorf("tls: invalid EncryptedClientHelloKey Config KEM: %s", err)
586 }
587 echPriv, err := kem.NewPrivateKey(echKey.PrivateKey)
588 if err != nil {
589 c.sendAlert(alertInternalError)
590 return nil, nil, fmt.Errorf("tls: invalid EncryptedClientHelloKey PrivateKey: %s", err)
591 }
592 kdf, err := hpke.NewKDF(echCiphersuite.KDFID)
593 if err != nil {
594 c.sendAlert(alertInternalError)
595 return nil, nil, fmt.Errorf("tls: invalid EncryptedClientHelloKey Config KDF: %s", err)
596 }
597 aead, err := hpke.NewAEAD(echCiphersuite.AEADID)
598 if err != nil {
599 c.sendAlert(alertInternalError)
600 return nil, nil, fmt.Errorf("tls: invalid EncryptedClientHelloKey Config AEAD: %s", err)
601 }
602 info := append([]byte("tls ech\x00"), echKey.Config...)
603 hpkeContext, err := hpke.NewRecipient(encap, echPriv, kdf, aead, info)
604 if err != nil {
605
606 continue
607 }
608
609 encodedInner, err := decryptECHPayload(hpkeContext, outer.original, payload)
610 if err != nil {
611
612 continue
613 }
614
615
616
617
618
619
620
621 echInner, err := decodeInnerClientHello(outer, encodedInner)
622 if err != nil {
623 c.sendAlert(alertIllegalParameter)
624 return nil, nil, errInvalidECHExt
625 }
626
627 c.echAccepted = true
628
629 return echInner, &echServerContext{
630 hpkeContext: hpkeContext,
631 configID: configID,
632 ciphersuite: echCiphersuite,
633 }, nil
634 }
635
636 return outer, nil, nil
637 }
638
639 func buildRetryConfigList(keys []EncryptedClientHelloKey) ([]byte, error) {
640 var atLeastOneRetryConfig bool
641 var retryBuilder cryptobyte.Builder
642 retryBuilder.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
643 for _, c := range keys {
644 if !c.SendAsRetry {
645 continue
646 }
647 atLeastOneRetryConfig = true
648 b.AddBytes(c.Config)
649 }
650 })
651 if !atLeastOneRetryConfig {
652 return nil, nil
653 }
654 return retryBuilder.Bytes()
655 }
656
View as plain text