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

View as plain text