Source file 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 [QUICConn.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 [QUICConn.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.handshakeMutex.Lock()
   232  	defer c.handshakeMutex.Unlock()
   233  	c.hand.Write(c.quic.readbuf)
   234  	c.quic.readbuf = nil
   235  	for q.conn.hand.Len() >= 4 && q.conn.handshakeErr == nil {
   236  		b := q.conn.hand.Bytes()
   237  		n := int(b[1])<<16 | int(b[2])<<8 | int(b[3])
   238  		if n > maxHandshake {
   239  			q.conn.handshakeErr = fmt.Errorf("tls: handshake message of length %d bytes exceeds maximum of %d bytes", n, maxHandshake)
   240  			break
   241  		}
   242  		if len(b) < 4+n {
   243  			return nil
   244  		}
   245  		if err := q.conn.handlePostHandshakeMessage(); err != nil {
   246  			q.conn.handshakeErr = err
   247  		}
   248  	}
   249  	if q.conn.handshakeErr != nil {
   250  		return quicError(q.conn.handshakeErr)
   251  	}
   252  	return nil
   253  }
   254  
   255  type QUICSessionTicketOptions struct {
   256  	// EarlyData specifies whether the ticket may be used for 0-RTT.
   257  	EarlyData bool
   258  }
   259  
   260  // SendSessionTicket sends a session ticket to the client.
   261  // It produces connection events, which may be read with [QUICConn.NextEvent].
   262  // Currently, it can only be called once.
   263  func (q *QUICConn) SendSessionTicket(opts QUICSessionTicketOptions) error {
   264  	c := q.conn
   265  	if !c.isHandshakeComplete.Load() {
   266  		return quicError(errors.New("tls: SendSessionTicket called before handshake completed"))
   267  	}
   268  	if c.isClient {
   269  		return quicError(errors.New("tls: SendSessionTicket called on the client"))
   270  	}
   271  	if q.sessionTicketSent {
   272  		return quicError(errors.New("tls: SendSessionTicket called multiple times"))
   273  	}
   274  	q.sessionTicketSent = true
   275  	return quicError(c.sendSessionTicket(opts.EarlyData))
   276  }
   277  
   278  // ConnectionState returns basic TLS details about the connection.
   279  func (q *QUICConn) ConnectionState() ConnectionState {
   280  	return q.conn.ConnectionState()
   281  }
   282  
   283  // SetTransportParameters sets the transport parameters to send to the peer.
   284  //
   285  // Server connections may delay setting the transport parameters until after
   286  // receiving the client's transport parameters. See [QUICTransportParametersRequired].
   287  func (q *QUICConn) SetTransportParameters(params []byte) {
   288  	if params == nil {
   289  		params = []byte{}
   290  	}
   291  	q.conn.quic.transportParams = params
   292  	if q.conn.quic.started {
   293  		<-q.conn.quic.signalc
   294  		<-q.conn.quic.blockedc
   295  	}
   296  }
   297  
   298  // quicError ensures err is an AlertError.
   299  // If err is not already, quicError wraps it with alertInternalError.
   300  func quicError(err error) error {
   301  	if err == nil {
   302  		return nil
   303  	}
   304  	var ae AlertError
   305  	if errors.As(err, &ae) {
   306  		return err
   307  	}
   308  	var a alert
   309  	if !errors.As(err, &a) {
   310  		a = alertInternalError
   311  	}
   312  	// Return an error wrapping the original error and an AlertError.
   313  	// Truncate the text of the alert to 0 characters.
   314  	return fmt.Errorf("%w%.0w", err, AlertError(a))
   315  }
   316  
   317  func (c *Conn) quicReadHandshakeBytes(n int) error {
   318  	for c.hand.Len() < n {
   319  		if err := c.quicWaitForSignal(); err != nil {
   320  			return err
   321  		}
   322  	}
   323  	return nil
   324  }
   325  
   326  func (c *Conn) quicSetReadSecret(level QUICEncryptionLevel, suite uint16, secret []byte) {
   327  	c.quic.events = append(c.quic.events, QUICEvent{
   328  		Kind:  QUICSetReadSecret,
   329  		Level: level,
   330  		Suite: suite,
   331  		Data:  secret,
   332  	})
   333  }
   334  
   335  func (c *Conn) quicSetWriteSecret(level QUICEncryptionLevel, suite uint16, secret []byte) {
   336  	c.quic.events = append(c.quic.events, QUICEvent{
   337  		Kind:  QUICSetWriteSecret,
   338  		Level: level,
   339  		Suite: suite,
   340  		Data:  secret,
   341  	})
   342  }
   343  
   344  func (c *Conn) quicWriteCryptoData(level QUICEncryptionLevel, data []byte) {
   345  	var last *QUICEvent
   346  	if len(c.quic.events) > 0 {
   347  		last = &c.quic.events[len(c.quic.events)-1]
   348  	}
   349  	if last == nil || last.Kind != QUICWriteData || last.Level != level {
   350  		c.quic.events = append(c.quic.events, QUICEvent{
   351  			Kind:  QUICWriteData,
   352  			Level: level,
   353  		})
   354  		last = &c.quic.events[len(c.quic.events)-1]
   355  	}
   356  	last.Data = append(last.Data, data...)
   357  }
   358  
   359  func (c *Conn) quicSetTransportParameters(params []byte) {
   360  	c.quic.events = append(c.quic.events, QUICEvent{
   361  		Kind: QUICTransportParameters,
   362  		Data: params,
   363  	})
   364  }
   365  
   366  func (c *Conn) quicGetTransportParameters() ([]byte, error) {
   367  	if c.quic.transportParams == nil {
   368  		c.quic.events = append(c.quic.events, QUICEvent{
   369  			Kind: QUICTransportParametersRequired,
   370  		})
   371  	}
   372  	for c.quic.transportParams == nil {
   373  		if err := c.quicWaitForSignal(); err != nil {
   374  			return nil, err
   375  		}
   376  	}
   377  	return c.quic.transportParams, nil
   378  }
   379  
   380  func (c *Conn) quicHandshakeComplete() {
   381  	c.quic.events = append(c.quic.events, QUICEvent{
   382  		Kind: QUICHandshakeDone,
   383  	})
   384  }
   385  
   386  func (c *Conn) quicRejectedEarlyData() {
   387  	c.quic.events = append(c.quic.events, QUICEvent{
   388  		Kind: QUICRejectedEarlyData,
   389  	})
   390  }
   391  
   392  // quicWaitForSignal notifies the QUICConn that handshake progress is blocked,
   393  // and waits for a signal that the handshake should proceed.
   394  //
   395  // The handshake may become blocked waiting for handshake bytes
   396  // or for the user to provide transport parameters.
   397  func (c *Conn) quicWaitForSignal() error {
   398  	// Drop the handshake mutex while blocked to allow the user
   399  	// to call ConnectionState before the handshake completes.
   400  	c.handshakeMutex.Unlock()
   401  	defer c.handshakeMutex.Lock()
   402  	// Send on blockedc to notify the QUICConn that the handshake is blocked.
   403  	// Exported methods of QUICConn wait for the handshake to become blocked
   404  	// before returning to the user.
   405  	select {
   406  	case c.quic.blockedc <- struct{}{}:
   407  	case <-c.quic.cancelc:
   408  		return c.sendAlertLocked(alertCloseNotify)
   409  	}
   410  	// The QUICConn reads from signalc to notify us that the handshake may
   411  	// be able to proceed. (The QUICConn reads, because we close signalc to
   412  	// indicate that the handshake has completed.)
   413  	select {
   414  	case c.quic.signalc <- struct{}{}:
   415  		c.hand.Write(c.quic.readbuf)
   416  		c.quic.readbuf = nil
   417  	case <-c.quic.cancelc:
   418  		return c.sendAlertLocked(alertCloseNotify)
   419  	}
   420  	return nil
   421  }
   422  

View as plain text