quic.go 12 KB

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