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 = 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 var outerExtensionsSeen bool
317 for !extensions.Empty() {
318 var extension uint16
319 var extData cryptobyte.String
320 if !extensions.ReadUint16(&extension) ||
321 !extensions.ReadUint16LengthPrefixed(&extData) {
322 recon.SetError(errors.New("tls: invalid inner client hello"))
323 return
324 }
325 if extension == extensionECHOuterExtensions {
326 if outerExtensionsSeen {
327 recon.SetError(errors.New("tls: invalid outer extensions"))
328 return
329 }
330 outerExtensionsSeen = true
331 var outerExtensions cryptobyte.String
332 if !extData.ReadUint8LengthPrefixed(&outerExtensions) || !extData.Empty() ||
333 outerExtensions.Empty() {
334 recon.SetError(errors.New("tls: invalid inner client hello"))
335 return
336 }
337
338
339
340
341 var i int
342 for !outerExtensions.Empty() {
343 var extType uint16
344 if !outerExtensions.ReadUint16(&extType) {
345 recon.SetError(errors.New("tls: invalid inner client hello"))
346 return
347 }
348 if extType == extensionEncryptedClientHello ||
349 extType == extensionECHOuterExtensions {
350 recon.SetError(errors.New("tls: invalid outer extensions"))
351 return
352 }
353 for ; i <= len(rawOuterExts); i++ {
354 if i == len(rawOuterExts) {
355 recon.SetError(errors.New("tls: invalid outer extensions"))
356 return
357 }
358 if rawOuterExts[i].extType == extType {
359 break
360 }
361 }
362 recon.AddUint16(rawOuterExts[i].extType)
363 recon.AddUint16LengthPrefixed(func(recon *cryptobyte.Builder) {
364 recon.AddBytes(rawOuterExts[i].data)
365 })
366 i++
367 }
368 } else {
369 recon.AddUint16(extension)
370 recon.AddUint16LengthPrefixed(func(recon *cryptobyte.Builder) {
371 recon.AddBytes(extData)
372 })
373 }
374 }
375 })
376 })
377
378 reconBytes, err := recon.Bytes()
379 if err != nil {
380 return nil, err
381 }
382 inner := &clientHelloMsg{}
383 if !inner.unmarshal(reconBytes) {
384 return nil, errors.New("tls: invalid reconstructed inner client hello")
385 }
386
387 if !bytes.Equal(inner.encryptedClientHello, []byte{uint8(innerECHExt)}) {
388 return nil, errInvalidECHExt
389 }
390
391 hasTLS13 := false
392 for _, v := range inner.supportedVersions {
393
394
395
396
397
398 if v&0x0F0F == 0x0A0A && v&0xff == v>>8 {
399 continue
400 }
401
402
403 if v == VersionTLS13 {
404 hasTLS13 = true
405 } else if v < VersionTLS13 {
406
407 return nil, errors.New("tls: client sent encrypted_client_hello extension with unsupported versions")
408 }
409 }
410
411 if !hasTLS13 {
412 return nil, errors.New("tls: client sent encrypted_client_hello extension but did not offer TLS 1.3")
413 }
414
415 return inner, nil
416 }
417
418 func decryptECHPayload(context *hpke.Recipient, hello, payload []byte) ([]byte, error) {
419 outerAAD := bytes.Replace(hello[4:], payload, make([]byte, len(payload)), 1)
420 return context.Open(outerAAD, payload)
421 }
422
423 func generateOuterECHExt(id uint8, kdfID, aeadID uint16, encodedKey []byte, payload []byte) ([]byte, error) {
424 var b cryptobyte.Builder
425 b.AddUint8(0)
426 b.AddUint16(kdfID)
427 b.AddUint16(aeadID)
428 b.AddUint8(id)
429 b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { b.AddBytes(encodedKey) })
430 b.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) { b.AddBytes(payload) })
431 return b.Bytes()
432 }
433
434 func computeAndUpdateOuterECHExtension(outer, inner *clientHelloMsg, ech *echClientContext, useKey bool) error {
435 var encapKey []byte
436 if useKey {
437 encapKey = ech.encapsulatedKey
438 }
439 encodedInner, err := encodeInnerClientHello(inner, int(ech.config.MaxNameLength))
440 if err != nil {
441 return err
442 }
443
444
445
446 encryptedLen := len(encodedInner) + 16
447 outer.encryptedClientHello, err = generateOuterECHExt(ech.config.ConfigID, ech.kdfID, ech.aeadID, encapKey, make([]byte, encryptedLen))
448 if err != nil {
449 return err
450 }
451 serializedOuter, err := outer.marshal()
452 if err != nil {
453 return err
454 }
455 serializedOuter = serializedOuter[4:]
456 encryptedInner, err := ech.hpkeContext.Seal(serializedOuter, encodedInner)
457 if err != nil {
458 return err
459 }
460 outer.encryptedClientHello, err = generateOuterECHExt(ech.config.ConfigID, ech.kdfID, ech.aeadID, encapKey, encryptedInner)
461 if err != nil {
462 return err
463 }
464 return nil
465 }
466
467
468
469
470
471 func validDNSName(name string) bool {
472 if len(name) > 253 {
473 return false
474 }
475 labels := strings.Split(name, ".")
476 if len(labels) <= 1 {
477 return false
478 }
479 for _, l := range labels {
480 labelLen := len(l)
481 if labelLen == 0 {
482 return false
483 }
484 for i, r := range l {
485 if r == '-' && (i == 0 || i == labelLen-1) {
486 return false
487 }
488 if (r < '0' || r > '9') && (r < 'a' || r > 'z') && (r < 'A' || r > 'Z') && r != '-' {
489 return false
490 }
491 }
492 }
493 return true
494 }
495
496
497
498
499
500
501
502 type ECHRejectionError struct {
503 RetryConfigList []byte
504 }
505
506 func (e *ECHRejectionError) Error() string {
507 return "tls: server rejected ECH"
508 }
509
510 var errMalformedECHExt = errors.New("tls: malformed encrypted_client_hello extension")
511 var errInvalidECHExt = errors.New("tls: client sent invalid encrypted_client_hello extension")
512
513 type echExtType uint8
514
515 const (
516 innerECHExt echExtType = 1
517 outerECHExt echExtType = 0
518 )
519
520 func parseECHExt(ext []byte) (echType echExtType, cs echCipher, configID uint8, encap []byte, payload []byte, err error) {
521 data := make([]byte, len(ext))
522 copy(data, ext)
523 s := cryptobyte.String(data)
524 var echInt uint8
525 if !s.ReadUint8(&echInt) {
526 err = errMalformedECHExt
527 return
528 }
529 echType = echExtType(echInt)
530 if echType == innerECHExt {
531 if !s.Empty() {
532 err = errMalformedECHExt
533 return
534 }
535 return echType, cs, 0, nil, nil, nil
536 }
537 if echType != outerECHExt {
538 err = errInvalidECHExt
539 return
540 }
541 if !s.ReadUint16(&cs.KDFID) {
542 err = errMalformedECHExt
543 return
544 }
545 if !s.ReadUint16(&cs.AEADID) {
546 err = errMalformedECHExt
547 return
548 }
549 if !s.ReadUint8(&configID) {
550 err = errMalformedECHExt
551 return
552 }
553 if !readUint16LengthPrefixed(&s, &encap) {
554 err = errMalformedECHExt
555 return
556 }
557 if !readUint16LengthPrefixed(&s, &payload) {
558 err = errMalformedECHExt
559 return
560 }
561
562
563
564 return echType, cs, configID, bytes.Clone(encap), bytes.Clone(payload), nil
565 }
566
567 func (c *Conn) processECHClientHello(outer *clientHelloMsg, echKeys []EncryptedClientHelloKey) (*clientHelloMsg, *echServerContext, error) {
568 echType, echCiphersuite, configID, encap, payload, err := parseECHExt(outer.encryptedClientHello)
569 if err != nil {
570 if errors.Is(err, errInvalidECHExt) {
571 c.sendAlert(alertIllegalParameter)
572 } else {
573 c.sendAlert(alertDecodeError)
574 }
575
576 return nil, nil, errInvalidECHExt
577 }
578
579 if echType == innerECHExt {
580 return outer, &echServerContext{inner: true}, nil
581 }
582
583 if len(echKeys) == 0 {
584 return outer, nil, nil
585 }
586
587 for _, echKey := range echKeys {
588 skip, config, err := parseECHConfig(echKey.Config)
589 if err != nil {
590 c.sendAlert(alertInternalError)
591 return nil, nil, fmt.Errorf("tls: invalid EncryptedClientHelloKey Config: %s", err)
592 }
593 if skip {
594 continue
595 }
596 kem, err := hpke.NewKEM(config.KemID)
597 if err != nil {
598 c.sendAlert(alertInternalError)
599 return nil, nil, fmt.Errorf("tls: invalid EncryptedClientHelloKey Config KEM: %s", err)
600 }
601 echPriv, err := kem.NewPrivateKey(echKey.PrivateKey)
602 if err != nil {
603 c.sendAlert(alertInternalError)
604 return nil, nil, fmt.Errorf("tls: invalid EncryptedClientHelloKey PrivateKey: %s", err)
605 }
606 kdf, err := hpke.NewKDF(echCiphersuite.KDFID)
607 if err != nil {
608 c.sendAlert(alertInternalError)
609 return nil, nil, fmt.Errorf("tls: invalid EncryptedClientHelloKey Config KDF: %s", err)
610 }
611 aead, err := hpke.NewAEAD(echCiphersuite.AEADID)
612 if err != nil {
613 c.sendAlert(alertInternalError)
614 return nil, nil, fmt.Errorf("tls: invalid EncryptedClientHelloKey Config AEAD: %s", err)
615 }
616 info := append([]byte("tls ech\x00"), echKey.Config...)
617 hpkeContext, err := hpke.NewRecipient(encap, echPriv, kdf, aead, info)
618 if err != nil {
619
620 continue
621 }
622
623 encodedInner, err := decryptECHPayload(hpkeContext, outer.original, payload)
624 if err != nil {
625
626 continue
627 }
628
629
630
631
632
633
634
635 echInner, err := decodeInnerClientHello(outer, encodedInner)
636 if err != nil {
637 c.sendAlert(alertIllegalParameter)
638 return nil, nil, errInvalidECHExt
639 }
640
641 c.echAccepted = true
642
643 return echInner, &echServerContext{
644 hpkeContext: hpkeContext,
645 configID: configID,
646 ciphersuite: echCiphersuite,
647 }, nil
648 }
649
650 return outer, nil, nil
651 }
652
653 func buildRetryConfigList(keys []EncryptedClientHelloKey) ([]byte, error) {
654 var atLeastOneRetryConfig bool
655 var retryBuilder cryptobyte.Builder
656 retryBuilder.AddUint16LengthPrefixed(func(b *cryptobyte.Builder) {
657 for _, c := range keys {
658 if !c.SendAsRetry {
659 continue
660 }
661 atLeastOneRetryConfig = true
662 b.AddBytes(c.Config)
663 }
664 })
665 if !atLeastOneRetryConfig {
666 return nil, nil
667 }
668 return retryBuilder.Bytes()
669 }
670
View as plain text