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