quic.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  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. // EnableSessionEvents may be set to true to enable the
  45. // [QUICStoreSession] and [QUICResumeSession] events for client connections.
  46. // When this event is enabled, sessions are not automatically
  47. // stored in the client session cache.
  48. // The application should use [QUICConn.StoreSession] to store sessions.
  49. EnableSessionEvents bool
  50. }
  51. // A QUICEventKind is a type of operation on a QUIC connection.
  52. type QUICEventKind int
  53. const (
  54. // QUICNoEvent indicates that there are no events available.
  55. QUICNoEvent QUICEventKind = iota
  56. // QUICSetReadSecret and QUICSetWriteSecret provide the read and write
  57. // secrets for a given encryption level.
  58. // QUICEvent.Level, QUICEvent.Data, and QUICEvent.Suite are set.
  59. //
  60. // Secrets for the Initial encryption level are derived from the initial
  61. // destination connection ID, and are not provided by the QUICConn.
  62. QUICSetReadSecret
  63. QUICSetWriteSecret
  64. // QUICWriteData provides data to send to the peer in CRYPTO frames.
  65. // QUICEvent.Data is set.
  66. QUICWriteData
  67. // QUICTransportParameters provides the peer's QUIC transport parameters.
  68. // QUICEvent.Data is set.
  69. QUICTransportParameters
  70. // QUICTransportParametersRequired indicates that the caller must provide
  71. // QUIC transport parameters to send to the peer. The caller should set
  72. // the transport parameters with QUICConn.SetTransportParameters and call
  73. // QUICConn.NextEvent again.
  74. //
  75. // If transport parameters are set before calling QUICConn.Start, the
  76. // connection will never generate a QUICTransportParametersRequired event.
  77. QUICTransportParametersRequired
  78. // QUICRejectedEarlyData indicates that the server rejected 0-RTT data even
  79. // if we offered it. It's returned before QUICEncryptionLevelApplication
  80. // keys are returned.
  81. // This event only occurs on client connections.
  82. QUICRejectedEarlyData
  83. // QUICHandshakeDone indicates that the TLS handshake has completed.
  84. QUICHandshakeDone
  85. // QUICResumeSession indicates that a client is attempting to resume a previous session.
  86. // [QUICEvent.SessionState] is set.
  87. //
  88. // For client connections, this event occurs when the session ticket is selected.
  89. // For server connections, this event occurs when receiving the client's session ticket.
  90. //
  91. // The application may set [QUICEvent.SessionState.EarlyData] to false before the
  92. // next call to [QUICConn.NextEvent] to decline 0-RTT even if the session supports it.
  93. QUICResumeSession
  94. // QUICStoreSession indicates that the server has provided state permitting
  95. // the client to resume the session.
  96. // [QUICEvent.SessionState] is set.
  97. // The application should use [QUICConn.StoreSession] session to store the [SessionState].
  98. // The application may modify the [SessionState] before storing it.
  99. // This event only occurs on client connections.
  100. QUICStoreSession
  101. )
  102. // A QUICEvent is an event occurring on a QUIC connection.
  103. //
  104. // The type of event is specified by the Kind field.
  105. // The contents of the other fields are kind-specific.
  106. type QUICEvent struct {
  107. Kind QUICEventKind
  108. // Set for QUICSetReadSecret, QUICSetWriteSecret, and QUICWriteData.
  109. Level QUICEncryptionLevel
  110. // Set for QUICTransportParameters, QUICSetReadSecret, QUICSetWriteSecret, and QUICWriteData.
  111. // The contents are owned by crypto/tls, and are valid until the next NextEvent call.
  112. Data []byte
  113. // Set for QUICSetReadSecret and QUICSetWriteSecret.
  114. Suite uint16
  115. // Set for QUICResumeSession and QUICStoreSession.
  116. SessionState *SessionState
  117. }
  118. type quicState struct {
  119. events []QUICEvent
  120. nextEvent int
  121. // eventArr is a statically allocated event array, large enough to handle
  122. // the usual maximum number of events resulting from a single call: transport
  123. // parameters, Initial data, Early read secret, Handshake write and read
  124. // secrets, Handshake data, Application write secret, Application data.
  125. eventArr [8]QUICEvent
  126. started bool
  127. signalc chan struct{} // handshake data is available to be read
  128. blockedc chan struct{} // handshake is waiting for data, closed when done
  129. cancelc <-chan struct{} // handshake has been canceled
  130. cancel context.CancelFunc
  131. waitingForDrain bool
  132. // readbuf is shared between HandleData and the handshake goroutine.
  133. // HandshakeCryptoData passes ownership to the handshake goroutine by
  134. // reading from signalc, and reclaims ownership by reading from blockedc.
  135. readbuf []byte
  136. transportParams []byte // to send to the peer
  137. enableSessionEvents bool
  138. }
  139. // QUICClient returns a new TLS client side connection using QUICTransport as the
  140. // underlying transport. The config cannot be nil.
  141. //
  142. // The config's MinVersion must be at least TLS 1.3.
  143. func QUICClient(config *QUICConfig) *QUICConn {
  144. return newQUICConn(Client(nil, config.TLSConfig), config)
  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), config)
  152. }
  153. func newQUICConn(conn *Conn, config *QUICConfig) *QUICConn {
  154. conn.quic = &quicState{
  155. signalc: make(chan struct{}),
  156. blockedc: make(chan struct{}),
  157. enableSessionEvents: config.EnableSessionEvents,
  158. }
  159. conn.quic.events = conn.quic.eventArr[:0]
  160. return &QUICConn{
  161. conn: conn,
  162. }
  163. }
  164. // Start starts the client or server handshake protocol.
  165. // It may produce connection events, which may be read with [QUICConn.NextEvent].
  166. //
  167. // Start must be called at most once.
  168. func (q *QUICConn) Start(ctx context.Context) error {
  169. if q.conn.quic.started {
  170. return quicError(errors.New("tls: Start called more than once"))
  171. }
  172. q.conn.quic.started = true
  173. if q.conn.config.MinVersion < VersionTLS13 {
  174. return quicError(errors.New("tls: Config MinVersion must be at least TLS 1.13"))
  175. }
  176. go q.conn.HandshakeContext(ctx)
  177. if _, ok := <-q.conn.quic.blockedc; !ok {
  178. return q.conn.handshakeErr
  179. }
  180. return nil
  181. }
  182. // NextEvent returns the next event occurring on the connection.
  183. // It returns an event with a Kind of [QUICNoEvent] when no events are available.
  184. func (q *QUICConn) NextEvent() QUICEvent {
  185. qs := q.conn.quic
  186. if last := qs.nextEvent - 1; last >= 0 && len(qs.events[last].Data) > 0 {
  187. // Write over some of the previous event's data,
  188. // to catch callers erroniously retaining it.
  189. qs.events[last].Data[0] = 0
  190. }
  191. if qs.nextEvent >= len(qs.events) && qs.waitingForDrain {
  192. qs.waitingForDrain = false
  193. <-qs.signalc
  194. <-qs.blockedc
  195. }
  196. if qs.nextEvent >= len(qs.events) {
  197. qs.events = qs.events[:0]
  198. qs.nextEvent = 0
  199. return QUICEvent{Kind: QUICNoEvent}
  200. }
  201. e := qs.events[qs.nextEvent]
  202. qs.events[qs.nextEvent] = QUICEvent{} // zero out references to data
  203. qs.nextEvent++
  204. return e
  205. }
  206. // Close closes the connection and stops any in-progress handshake.
  207. func (q *QUICConn) Close() error {
  208. if q.conn.quic.cancel == nil {
  209. return nil // never started
  210. }
  211. q.conn.quic.cancel()
  212. for range q.conn.quic.blockedc {
  213. // Wait for the handshake goroutine to return.
  214. }
  215. return q.conn.handshakeErr
  216. }
  217. // HandleData handles handshake bytes received from the peer.
  218. // It may produce connection events, which may be read with [QUICConn.NextEvent].
  219. func (q *QUICConn) HandleData(level QUICEncryptionLevel, data []byte) error {
  220. c := q.conn
  221. if c.in.level != level {
  222. return quicError(c.in.setErrorLocked(errors.New("tls: handshake data received at wrong level")))
  223. }
  224. c.quic.readbuf = data
  225. <-c.quic.signalc
  226. _, ok := <-c.quic.blockedc
  227. if ok {
  228. // The handshake goroutine is waiting for more data.
  229. return nil
  230. }
  231. // The handshake goroutine has exited.
  232. c.handshakeMutex.Lock()
  233. defer c.handshakeMutex.Unlock()
  234. c.hand.Write(c.quic.readbuf)
  235. c.quic.readbuf = nil
  236. for q.conn.hand.Len() >= 4 && q.conn.handshakeErr == nil {
  237. b := q.conn.hand.Bytes()
  238. n := int(b[1])<<16 | int(b[2])<<8 | int(b[3])
  239. if n > maxHandshake {
  240. q.conn.handshakeErr = fmt.Errorf("tls: handshake message of length %d bytes exceeds maximum of %d bytes", n, maxHandshake)
  241. break
  242. }
  243. if len(b) < 4+n {
  244. return nil
  245. }
  246. if err := q.conn.handlePostHandshakeMessage(); err != nil {
  247. q.conn.handshakeErr = err
  248. }
  249. }
  250. if q.conn.handshakeErr != nil {
  251. return quicError(q.conn.handshakeErr)
  252. }
  253. return nil
  254. }
  255. type QUICSessionTicketOptions struct {
  256. // EarlyData specifies whether the ticket may be used for 0-RTT.
  257. EarlyData bool
  258. Extra [][]byte
  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, opts.Extra))
  276. }
  277. // StoreSession stores a session previously received in a QUICStoreSession event
  278. // in the ClientSessionCache.
  279. // The application may process additional events or modify the SessionState
  280. // before storing the session.
  281. func (q *QUICConn) StoreSession(session *SessionState) error {
  282. c := q.conn
  283. if !c.isClient {
  284. return quicError(errors.New("tls: StoreSessionTicket called on the server"))
  285. }
  286. cacheKey := c.clientSessionCacheKey()
  287. if cacheKey == "" {
  288. return nil
  289. }
  290. cs := &ClientSessionState{session: session}
  291. c.config.ClientSessionCache.Put(cacheKey, cs)
  292. return nil
  293. }
  294. // ConnectionState returns basic TLS details about the connection.
  295. func (q *QUICConn) ConnectionState() ConnectionState {
  296. return q.conn.ConnectionState()
  297. }
  298. // [Psiphon]
  299. // TLSConnectionMetrics returns metrics of interest about the connection
  300. // that are not available from ConnectionState.
  301. func (q *QUICConn) TLSConnectionMetrics() ConnectionMetrics {
  302. return q.conn.ConnectionMetrics()
  303. }
  304. // SetTransportParameters sets the transport parameters to send to the peer.
  305. //
  306. // Server connections may delay setting the transport parameters until after
  307. // receiving the client's transport parameters. See [QUICTransportParametersRequired].
  308. func (q *QUICConn) SetTransportParameters(params []byte) {
  309. if params == nil {
  310. params = []byte{}
  311. }
  312. q.conn.quic.transportParams = params
  313. if q.conn.quic.started {
  314. <-q.conn.quic.signalc
  315. <-q.conn.quic.blockedc
  316. }
  317. }
  318. // quicError ensures err is an AlertError.
  319. // If err is not already, quicError wraps it with alertInternalError.
  320. func quicError(err error) error {
  321. if err == nil {
  322. return nil
  323. }
  324. var ae AlertError
  325. if errors.As(err, &ae) {
  326. return err
  327. }
  328. var a alert
  329. if !errors.As(err, &a) {
  330. a = alertInternalError
  331. }
  332. // Return an error wrapping the original error and an AlertError.
  333. // Truncate the text of the alert to 0 characters.
  334. return fmt.Errorf("%w%.0w", err, AlertError(a))
  335. }
  336. func (c *Conn) quicReadHandshakeBytes(n int) error {
  337. for c.hand.Len() < n {
  338. if err := c.quicWaitForSignal(); err != nil {
  339. return err
  340. }
  341. }
  342. return nil
  343. }
  344. func (c *Conn) quicSetReadSecret(level QUICEncryptionLevel, suite uint16, secret []byte) {
  345. c.quic.events = append(c.quic.events, QUICEvent{
  346. Kind: QUICSetReadSecret,
  347. Level: level,
  348. Suite: suite,
  349. Data: secret,
  350. })
  351. }
  352. func (c *Conn) quicSetWriteSecret(level QUICEncryptionLevel, suite uint16, secret []byte) {
  353. c.quic.events = append(c.quic.events, QUICEvent{
  354. Kind: QUICSetWriteSecret,
  355. Level: level,
  356. Suite: suite,
  357. Data: secret,
  358. })
  359. }
  360. func (c *Conn) quicWriteCryptoData(level QUICEncryptionLevel, data []byte) {
  361. var last *QUICEvent
  362. if len(c.quic.events) > 0 {
  363. last = &c.quic.events[len(c.quic.events)-1]
  364. }
  365. if last == nil || last.Kind != QUICWriteData || last.Level != level {
  366. c.quic.events = append(c.quic.events, QUICEvent{
  367. Kind: QUICWriteData,
  368. Level: level,
  369. })
  370. last = &c.quic.events[len(c.quic.events)-1]
  371. }
  372. last.Data = append(last.Data, data...)
  373. }
  374. func (c *Conn) quicResumeSession(session *SessionState) error {
  375. c.quic.events = append(c.quic.events, QUICEvent{
  376. Kind: QUICResumeSession,
  377. SessionState: session,
  378. })
  379. c.quic.waitingForDrain = true
  380. for c.quic.waitingForDrain {
  381. if err := c.quicWaitForSignal(); err != nil {
  382. return err
  383. }
  384. }
  385. return nil
  386. }
  387. func (c *Conn) quicStoreSession(session *SessionState) {
  388. c.quic.events = append(c.quic.events, QUICEvent{
  389. Kind: QUICStoreSession,
  390. SessionState: session,
  391. })
  392. }
  393. func (c *Conn) quicSetTransportParameters(params []byte) {
  394. c.quic.events = append(c.quic.events, QUICEvent{
  395. Kind: QUICTransportParameters,
  396. Data: params,
  397. })
  398. }
  399. func (c *Conn) quicGetTransportParameters() ([]byte, error) {
  400. if c.quic.transportParams == nil {
  401. c.quic.events = append(c.quic.events, QUICEvent{
  402. Kind: QUICTransportParametersRequired,
  403. })
  404. }
  405. for c.quic.transportParams == nil {
  406. if err := c.quicWaitForSignal(); err != nil {
  407. return nil, err
  408. }
  409. }
  410. return c.quic.transportParams, nil
  411. }
  412. func (c *Conn) quicHandshakeComplete() {
  413. c.quic.events = append(c.quic.events, QUICEvent{
  414. Kind: QUICHandshakeDone,
  415. })
  416. }
  417. func (c *Conn) quicRejectedEarlyData() {
  418. c.quic.events = append(c.quic.events, QUICEvent{
  419. Kind: QUICRejectedEarlyData,
  420. })
  421. }
  422. // quicWaitForSignal notifies the QUICConn that handshake progress is blocked,
  423. // and waits for a signal that the handshake should proceed.
  424. //
  425. // The handshake may become blocked waiting for handshake bytes
  426. // or for the user to provide transport parameters.
  427. func (c *Conn) quicWaitForSignal() error {
  428. // Drop the handshake mutex while blocked to allow the user
  429. // to call ConnectionState before the handshake completes.
  430. c.handshakeMutex.Unlock()
  431. defer c.handshakeMutex.Lock()
  432. // Send on blockedc to notify the QUICConn that the handshake is blocked.
  433. // Exported methods of QUICConn wait for the handshake to become blocked
  434. // before returning to the user.
  435. select {
  436. case c.quic.blockedc <- struct{}{}:
  437. case <-c.quic.cancelc:
  438. return c.sendAlertLocked(alertCloseNotify)
  439. }
  440. // The QUICConn reads from signalc to notify us that the handshake may
  441. // be able to proceed. (The QUICConn reads, because we close signalc to
  442. // indicate that the handshake has completed.)
  443. select {
  444. case c.quic.signalc <- struct{}{}:
  445. c.hand.Write(c.quic.readbuf)
  446. c.quic.readbuf = nil
  447. case <-c.quic.cancelc:
  448. return c.sendAlertLocked(alertCloseNotify)
  449. }
  450. return nil
  451. }