]> Cypherpunks.ru repositories - gostls13.git/blob - src/crypto/tls/quic.go
a59b893738ee6dce674367cf678ccabdc44941b9
[gostls13.git] / src / crypto / tls / quic.go
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 package tls
6
7 import (
8         "context"
9         "errors"
10         "fmt"
11 )
12
13 // QUICEncryptionLevel represents a QUIC encryption level used to transmit
14 // handshake messages.
15 type QUICEncryptionLevel int
16
17 const (
18         QUICEncryptionLevelInitial = QUICEncryptionLevel(iota)
19         QUICEncryptionLevelHandshake
20         QUICEncryptionLevelApplication
21 )
22
23 func (l QUICEncryptionLevel) String() string {
24         switch l {
25         case QUICEncryptionLevelInitial:
26                 return "Initial"
27         case QUICEncryptionLevelHandshake:
28                 return "Handshake"
29         case QUICEncryptionLevelApplication:
30                 return "Application"
31         default:
32                 return fmt.Sprintf("QUICEncryptionLevel(%v)", int(l))
33         }
34 }
35
36 // A QUICConn represents a connection which uses a QUIC implementation as the underlying
37 // transport as described in RFC 9001.
38 //
39 // Methods of QUICConn are not safe for concurrent use.
40 type QUICConn struct {
41         conn *Conn
42 }
43
44 // A QUICConfig configures a QUICConn.
45 type QUICConfig struct {
46         TLSConfig *Config
47 }
48
49 // A QUICEventKind is a type of operation on a QUIC connection.
50 type QUICEventKind int
51
52 const (
53         // QUICNoEvent indicates that there are no events available.
54         QUICNoEvent QUICEventKind = iota
55
56         // QUICSetReadSecret and QUICSetWriteSecret provide the read and write
57         // secrets for a given encryption level.
58         // QUICEvent.Level, QUICEvent.Data, and QUICEvent.Suite are set.
59         //
60         // Secrets for the Initial encryption level are derived from the initial
61         // destination connection ID, and are not provided by the QUICConn.
62         QUICSetReadSecret
63         QUICSetWriteSecret
64
65         // QUICWriteData provides data to send to the peer in CRYPTO frames.
66         // QUICEvent.Data is set.
67         QUICWriteData
68
69         // QUICTransportParameters provides the peer's QUIC transport parameters.
70         // QUICEvent.Data is set.
71         QUICTransportParameters
72
73         // QUICTransportParametersRequired indicates that the caller must provide
74         // QUIC transport parameters to send to the peer. The caller should set
75         // the transport parameters with QUICConn.SetTransportParameters and call
76         // QUICConn.NextEvent again.
77         //
78         // If transport parameters are set before calling QUICConn.Start, the
79         // connection will never generate a QUICTransportParametersRequired event.
80         QUICTransportParametersRequired
81
82         // QUICHandshakeDone indicates that the TLS handshake has completed.
83         QUICHandshakeDone
84 )
85
86 // A QUICEvent is an event occurring on a QUIC connection.
87 //
88 // The type of event is specified by the Kind field.
89 // The contents of the other fields are kind-specific.
90 type QUICEvent struct {
91         Kind QUICEventKind
92
93         // Set for QUICSetReadSecret, QUICSetWriteSecret, and QUICWriteData.
94         Level QUICEncryptionLevel
95
96         // Set for QUICTransportParameters, QUICSetReadSecret, QUICSetWriteSecret, and QUICWriteData.
97         // The contents are owned by crypto/tls, and are valid until the next NextEvent call.
98         Data []byte
99
100         // Set for QUICSetReadSecret and QUICSetWriteSecret.
101         Suite uint16
102 }
103
104 type quicState struct {
105         events    []QUICEvent
106         nextEvent int
107
108         // eventArr is a statically allocated event array, large enough to handle
109         // the usual maximum number of events resulting from a single call:
110         // transport parameters, Initial data, Handshake write and read secrets,
111         // Handshake data, Application write secret, Application data.
112         eventArr [7]QUICEvent
113
114         started  bool
115         signalc  chan struct{}   // handshake data is available to be read
116         blockedc chan struct{}   // handshake is waiting for data, closed when done
117         cancelc  <-chan struct{} // handshake has been canceled
118         cancel   context.CancelFunc
119
120         // readbuf is shared between HandleData and the handshake goroutine.
121         // HandshakeCryptoData passes ownership to the handshake goroutine by
122         // reading from signalc, and reclaims ownership by reading from blockedc.
123         readbuf []byte
124
125         transportParams []byte // to send to the peer
126 }
127
128 // QUICClient returns a new TLS client side connection using QUICTransport as the
129 // underlying transport. The config cannot be nil.
130 //
131 // The config's MinVersion must be at least TLS 1.3.
132 func QUICClient(config *QUICConfig) *QUICConn {
133         return newQUICConn(Client(nil, config.TLSConfig))
134 }
135
136 // QUICServer returns a new TLS server side connection using QUICTransport as the
137 // underlying transport. The config cannot be nil.
138 //
139 // The config's MinVersion must be at least TLS 1.3.
140 func QUICServer(config *QUICConfig) *QUICConn {
141         return newQUICConn(Server(nil, config.TLSConfig))
142 }
143
144 func newQUICConn(conn *Conn) *QUICConn {
145         conn.quic = &quicState{
146                 signalc:  make(chan struct{}),
147                 blockedc: make(chan struct{}),
148         }
149         conn.quic.events = conn.quic.eventArr[:0]
150         return &QUICConn{
151                 conn: conn,
152         }
153 }
154
155 // Start starts the client or server handshake protocol.
156 // It may produce connection events, which may be read with NextEvent.
157 //
158 // Start must be called at most once.
159 func (q *QUICConn) Start(ctx context.Context) error {
160         if q.conn.quic.started {
161                 return quicError(errors.New("tls: Start called more than once"))
162         }
163         q.conn.quic.started = true
164         if q.conn.config.MinVersion < VersionTLS13 {
165                 return quicError(errors.New("tls: Config MinVersion must be at least TLS 1.13"))
166         }
167         go q.conn.HandshakeContext(ctx)
168         if _, ok := <-q.conn.quic.blockedc; !ok {
169                 return q.conn.handshakeErr
170         }
171         return nil
172 }
173
174 // NextEvent returns the next event occurring on the connection.
175 // It returns an event with a Kind of QUICNoEvent when no events are available.
176 func (q *QUICConn) NextEvent() QUICEvent {
177         qs := q.conn.quic
178         if last := qs.nextEvent - 1; last >= 0 && len(qs.events[last].Data) > 0 {
179                 // Write over some of the previous event's data,
180                 // to catch callers erroniously retaining it.
181                 qs.events[last].Data[0] = 0
182         }
183         if qs.nextEvent >= len(qs.events) {
184                 qs.events = qs.events[:0]
185                 qs.nextEvent = 0
186                 return QUICEvent{Kind: QUICNoEvent}
187         }
188         e := qs.events[qs.nextEvent]
189         qs.events[qs.nextEvent] = QUICEvent{} // zero out references to data
190         qs.nextEvent++
191         return e
192 }
193
194 // Close closes the connection and stops any in-progress handshake.
195 func (q *QUICConn) Close() error {
196         if q.conn.quic.cancel == nil {
197                 return nil // never started
198         }
199         q.conn.quic.cancel()
200         for range q.conn.quic.blockedc {
201                 // Wait for the handshake goroutine to return.
202         }
203         return q.conn.handshakeErr
204 }
205
206 // HandleData handles handshake bytes received from the peer.
207 // It may produce connection events, which may be read with NextEvent.
208 func (q *QUICConn) HandleData(level QUICEncryptionLevel, data []byte) error {
209         c := q.conn
210         if c.in.level != level {
211                 return quicError(c.in.setErrorLocked(errors.New("tls: handshake data received at wrong level")))
212         }
213         c.quic.readbuf = data
214         <-c.quic.signalc
215         _, ok := <-c.quic.blockedc
216         if ok {
217                 // The handshake goroutine is waiting for more data.
218                 return nil
219         }
220         // The handshake goroutine has exited.
221         c.hand.Write(c.quic.readbuf)
222         c.quic.readbuf = nil
223         for q.conn.hand.Len() >= 4 && q.conn.handshakeErr == nil {
224                 b := q.conn.hand.Bytes()
225                 n := int(b[1])<<16 | int(b[2])<<8 | int(b[3])
226                 if 4+n < len(b) {
227                         return nil
228                 }
229                 if err := q.conn.handlePostHandshakeMessage(); err != nil {
230                         return quicError(err)
231                 }
232         }
233         if q.conn.handshakeErr != nil {
234                 return quicError(q.conn.handshakeErr)
235         }
236         return nil
237 }
238
239 // ConnectionState returns basic TLS details about the connection.
240 func (q *QUICConn) ConnectionState() ConnectionState {
241         return q.conn.ConnectionState()
242 }
243
244 // SetTransportParameters sets the transport parameters to send to the peer.
245 //
246 // Server connections may delay setting the transport parameters until after
247 // receiving the client's transport parameters. See QUICTransportParametersRequired.
248 func (q *QUICConn) SetTransportParameters(params []byte) {
249         if params == nil {
250                 params = []byte{}
251         }
252         q.conn.quic.transportParams = params
253         if q.conn.quic.started {
254                 <-q.conn.quic.signalc
255                 <-q.conn.quic.blockedc
256         }
257 }
258
259 // quicError ensures err is an AlertError.
260 // If err is not already, quicError wraps it with alertInternalError.
261 func quicError(err error) error {
262         if err == nil {
263                 return nil
264         }
265         var ae AlertError
266         if errors.As(err, &ae) {
267                 return err
268         }
269         var a alert
270         if !errors.As(err, &a) {
271                 a = alertInternalError
272         }
273         // Return an error wrapping the original error and an AlertError.
274         // Truncate the text of the alert to 0 characters.
275         return fmt.Errorf("%w%.0w", err, AlertError(a))
276 }
277
278 func (c *Conn) quicReadHandshakeBytes(n int) error {
279         for c.hand.Len() < n {
280                 if err := c.quicWaitForSignal(); err != nil {
281                         return err
282                 }
283         }
284         return nil
285 }
286
287 func (c *Conn) quicSetReadSecret(level QUICEncryptionLevel, suite uint16, secret []byte) {
288         c.quic.events = append(c.quic.events, QUICEvent{
289                 Kind:  QUICSetReadSecret,
290                 Level: level,
291                 Suite: suite,
292                 Data:  secret,
293         })
294 }
295
296 func (c *Conn) quicSetWriteSecret(level QUICEncryptionLevel, suite uint16, secret []byte) {
297         c.quic.events = append(c.quic.events, QUICEvent{
298                 Kind:  QUICSetWriteSecret,
299                 Level: level,
300                 Suite: suite,
301                 Data:  secret,
302         })
303 }
304
305 func (c *Conn) quicWriteCryptoData(level QUICEncryptionLevel, data []byte) {
306         var last *QUICEvent
307         if len(c.quic.events) > 0 {
308                 last = &c.quic.events[len(c.quic.events)-1]
309         }
310         if last == nil || last.Kind != QUICWriteData || last.Level != level {
311                 c.quic.events = append(c.quic.events, QUICEvent{
312                         Kind:  QUICWriteData,
313                         Level: level,
314                 })
315                 last = &c.quic.events[len(c.quic.events)-1]
316         }
317         last.Data = append(last.Data, data...)
318 }
319
320 func (c *Conn) quicSetTransportParameters(params []byte) {
321         c.quic.events = append(c.quic.events, QUICEvent{
322                 Kind: QUICTransportParameters,
323                 Data: params,
324         })
325 }
326
327 func (c *Conn) quicGetTransportParameters() ([]byte, error) {
328         if c.quic.transportParams == nil {
329                 c.quic.events = append(c.quic.events, QUICEvent{
330                         Kind: QUICTransportParametersRequired,
331                 })
332         }
333         for c.quic.transportParams == nil {
334                 if err := c.quicWaitForSignal(); err != nil {
335                         return nil, err
336                 }
337         }
338         return c.quic.transportParams, nil
339 }
340
341 func (c *Conn) quicHandshakeComplete() {
342         c.quic.events = append(c.quic.events, QUICEvent{
343                 Kind: QUICHandshakeDone,
344         })
345 }
346
347 // quicWaitForSignal notifies the QUICConn that handshake progress is blocked,
348 // and waits for a signal that the handshake should proceed.
349 //
350 // The handshake may become blocked waiting for handshake bytes
351 // or for the user to provide transport parameters.
352 func (c *Conn) quicWaitForSignal() error {
353         // Drop the handshake mutex while blocked to allow the user
354         // to call ConnectionState before the handshake completes.
355         c.handshakeMutex.Unlock()
356         defer c.handshakeMutex.Lock()
357         // Send on blockedc to notify the QUICConn that the handshake is blocked.
358         // Exported methods of QUICConn wait for the handshake to become blocked
359         // before returning to the user.
360         select {
361         case c.quic.blockedc <- struct{}{}:
362         case <-c.quic.cancelc:
363                 return c.sendAlertLocked(alertCloseNotify)
364         }
365         // The QUICConn reads from signalc to notify us that the handshake may
366         // be able to proceed. (The QUICConn reads, because we close signalc to
367         // indicate that the handshake has completed.)
368         select {
369         case c.quic.signalc <- struct{}{}:
370                 c.hand.Write(c.quic.readbuf)
371                 c.quic.readbuf = nil
372         case <-c.quic.cancelc:
373                 return c.sendAlertLocked(alertCloseNotify)
374         }
375         return nil
376 }