github.com/JimmyHuang454/JLS-go@v0.0.0-20230831150107-90d536585ba0/tls/quic.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 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 }