golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/tls.go (about) 1 // Copyright 2023 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 5 //go:build go1.21 6 7 package quic 8 9 import ( 10 "context" 11 "crypto/tls" 12 "errors" 13 "fmt" 14 "net" 15 "time" 16 ) 17 18 // startTLS starts the TLS handshake. 19 func (c *Conn) startTLS(now time.Time, initialConnID []byte, peerHostname string, params transportParameters) error { 20 tlsConfig := c.config.TLSConfig 21 if a, _, err := net.SplitHostPort(peerHostname); err == nil { 22 peerHostname = a 23 } 24 if tlsConfig.ServerName == "" && peerHostname != "" { 25 tlsConfig = tlsConfig.Clone() 26 tlsConfig.ServerName = peerHostname 27 } 28 29 c.keysInitial = initialKeys(initialConnID, c.side) 30 31 qconfig := &tls.QUICConfig{TLSConfig: tlsConfig} 32 if c.side == clientSide { 33 c.tls = tls.QUICClient(qconfig) 34 } else { 35 c.tls = tls.QUICServer(qconfig) 36 } 37 c.tls.SetTransportParameters(marshalTransportParameters(params)) 38 // TODO: We don't need or want a context for cancelation here, 39 // but users can use a context to plumb values through to hooks defined 40 // in the tls.Config. Pass through a context. 41 if err := c.tls.Start(context.TODO()); err != nil { 42 return err 43 } 44 return c.handleTLSEvents(now) 45 } 46 47 func (c *Conn) handleTLSEvents(now time.Time) error { 48 for { 49 e := c.tls.NextEvent() 50 if c.testHooks != nil { 51 c.testHooks.handleTLSEvent(e) 52 } 53 switch e.Kind { 54 case tls.QUICNoEvent: 55 return nil 56 case tls.QUICSetReadSecret: 57 if err := checkCipherSuite(e.Suite); err != nil { 58 return err 59 } 60 switch e.Level { 61 case tls.QUICEncryptionLevelHandshake: 62 c.keysHandshake.r.init(e.Suite, e.Data) 63 case tls.QUICEncryptionLevelApplication: 64 c.keysAppData.r.init(e.Suite, e.Data) 65 } 66 case tls.QUICSetWriteSecret: 67 if err := checkCipherSuite(e.Suite); err != nil { 68 return err 69 } 70 switch e.Level { 71 case tls.QUICEncryptionLevelHandshake: 72 c.keysHandshake.w.init(e.Suite, e.Data) 73 case tls.QUICEncryptionLevelApplication: 74 c.keysAppData.w.init(e.Suite, e.Data) 75 } 76 case tls.QUICWriteData: 77 var space numberSpace 78 switch e.Level { 79 case tls.QUICEncryptionLevelInitial: 80 space = initialSpace 81 case tls.QUICEncryptionLevelHandshake: 82 space = handshakeSpace 83 case tls.QUICEncryptionLevelApplication: 84 space = appDataSpace 85 default: 86 return fmt.Errorf("quic: internal error: write handshake data at level %v", e.Level) 87 } 88 c.crypto[space].write(e.Data) 89 case tls.QUICHandshakeDone: 90 if c.side == serverSide { 91 // "[...] the TLS handshake is considered confirmed 92 // at the server when the handshake completes." 93 // https://www.rfc-editor.org/rfc/rfc9001#section-4.1.2-1 94 c.confirmHandshake(now) 95 } 96 c.handshakeDone() 97 case tls.QUICTransportParameters: 98 params, err := unmarshalTransportParams(e.Data) 99 if err != nil { 100 return err 101 } 102 if err := c.receiveTransportParameters(params); err != nil { 103 return err 104 } 105 } 106 } 107 } 108 109 // handleCrypto processes data received in a CRYPTO frame. 110 func (c *Conn) handleCrypto(now time.Time, space numberSpace, off int64, data []byte) error { 111 var level tls.QUICEncryptionLevel 112 switch space { 113 case initialSpace: 114 level = tls.QUICEncryptionLevelInitial 115 case handshakeSpace: 116 level = tls.QUICEncryptionLevelHandshake 117 case appDataSpace: 118 level = tls.QUICEncryptionLevelApplication 119 default: 120 return errors.New("quic: internal error: received CRYPTO frame in unexpected number space") 121 } 122 err := c.crypto[space].handleCrypto(off, data, func(b []byte) error { 123 return c.tls.HandleData(level, b) 124 }) 125 if err != nil { 126 return err 127 } 128 return c.handleTLSEvents(now) 129 }