quic.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  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. // SetTransportParameters sets the transport parameters to send to the peer.
  299. //
  300. // Server connections may delay setting the transport parameters until after
  301. // receiving the client's transport parameters. See [QUICTransportParametersRequired].
  302. func (q *QUICConn) SetTransportParameters(params []byte) {
  303. if params == nil {
  304. params = []byte{}
  305. }
  306. q.conn.quic.transportParams = params
  307. if q.conn.quic.started {
  308. <-q.conn.quic.signalc
  309. <-q.conn.quic.blockedc
  310. }
  311. }
  312. // quicError ensures err is an AlertError.
  313. // If err is not already, quicError wraps it with alertInternalError.
  314. func quicError(err error) error {
  315. if err == nil {
  316. return nil
  317. }
  318. var ae AlertError
  319. if errors.As(err, &ae) {
  320. return err
  321. }
  322. var a alert
  323. if !errors.As(err, &a) {
  324. a = alertInternalError
  325. }
  326. // Return an error wrapping the original error and an AlertError.
  327. // Truncate the text of the alert to 0 characters.
  328. return fmt.Errorf("%w%.0w", err, AlertError(a))
  329. }
  330. func (c *Conn) quicReadHandshakeBytes(n int) error {
  331. for c.hand.Len() < n {
  332. if err := c.quicWaitForSignal(); err != nil {
  333. return err
  334. }
  335. }
  336. return nil
  337. }
  338. func (c *Conn) quicSetReadSecret(level QUICEncryptionLevel, suite uint16, secret []byte) {
  339. c.quic.events = append(c.quic.events, QUICEvent{
  340. Kind: QUICSetReadSecret,
  341. Level: level,
  342. Suite: suite,
  343. Data: secret,
  344. })
  345. }
  346. func (c *Conn) quicSetWriteSecret(level QUICEncryptionLevel, suite uint16, secret []byte) {
  347. c.quic.events = append(c.quic.events, QUICEvent{
  348. Kind: QUICSetWriteSecret,
  349. Level: level,
  350. Suite: suite,
  351. Data: secret,
  352. })
  353. }
  354. func (c *Conn) quicWriteCryptoData(level QUICEncryptionLevel, data []byte) {
  355. var last *QUICEvent
  356. if len(c.quic.events) > 0 {
  357. last = &c.quic.events[len(c.quic.events)-1]
  358. }
  359. if last == nil || last.Kind != QUICWriteData || last.Level != level {
  360. c.quic.events = append(c.quic.events, QUICEvent{
  361. Kind: QUICWriteData,
  362. Level: level,
  363. })
  364. last = &c.quic.events[len(c.quic.events)-1]
  365. }
  366. last.Data = append(last.Data, data...)
  367. }
  368. func (c *Conn) quicResumeSession(session *SessionState) error {
  369. c.quic.events = append(c.quic.events, QUICEvent{
  370. Kind: QUICResumeSession,
  371. SessionState: session,
  372. })
  373. c.quic.waitingForDrain = true
  374. for c.quic.waitingForDrain {
  375. if err := c.quicWaitForSignal(); err != nil {
  376. return err
  377. }
  378. }
  379. return nil
  380. }
  381. func (c *Conn) quicStoreSession(session *SessionState) {
  382. c.quic.events = append(c.quic.events, QUICEvent{
  383. Kind: QUICStoreSession,
  384. SessionState: session,
  385. })
  386. }
  387. func (c *Conn) quicSetTransportParameters(params []byte) {
  388. c.quic.events = append(c.quic.events, QUICEvent{
  389. Kind: QUICTransportParameters,
  390. Data: params,
  391. })
  392. }
  393. func (c *Conn) quicGetTransportParameters() ([]byte, error) {
  394. if c.quic.transportParams == nil {
  395. c.quic.events = append(c.quic.events, QUICEvent{
  396. Kind: QUICTransportParametersRequired,
  397. })
  398. }
  399. for c.quic.transportParams == nil {
  400. if err := c.quicWaitForSignal(); err != nil {
  401. return nil, err
  402. }
  403. }
  404. return c.quic.transportParams, nil
  405. }
  406. func (c *Conn) quicHandshakeComplete() {
  407. c.quic.events = append(c.quic.events, QUICEvent{
  408. Kind: QUICHandshakeDone,
  409. })
  410. }
  411. func (c *Conn) quicRejectedEarlyData() {
  412. c.quic.events = append(c.quic.events, QUICEvent{
  413. Kind: QUICRejectedEarlyData,
  414. })
  415. }
  416. // quicWaitForSignal notifies the QUICConn that handshake progress is blocked,
  417. // and waits for a signal that the handshake should proceed.
  418. //
  419. // The handshake may become blocked waiting for handshake bytes
  420. // or for the user to provide transport parameters.
  421. func (c *Conn) quicWaitForSignal() error {
  422. // Drop the handshake mutex while blocked to allow the user
  423. // to call ConnectionState before the handshake completes.
  424. c.handshakeMutex.Unlock()
  425. defer c.handshakeMutex.Lock()
  426. // Send on blockedc to notify the QUICConn that the handshake is blocked.
  427. // Exported methods of QUICConn wait for the handshake to become blocked
  428. // before returning to the user.
  429. select {
  430. case c.quic.blockedc <- struct{}{}:
  431. case <-c.quic.cancelc:
  432. return c.sendAlertLocked(alertCloseNotify)
  433. }
  434. // The QUICConn reads from signalc to notify us that the handshake may
  435. // be able to proceed. (The QUICConn reads, because we close signalc to
  436. // indicate that the handshake has completed.)
  437. select {
  438. case c.quic.signalc <- struct{}{}:
  439. c.hand.Write(c.quic.readbuf)
  440. c.quic.readbuf = nil
  441. case <-c.quic.cancelc:
  442. return c.sendAlertLocked(alertCloseNotify)
  443. }
  444. return nil
  445. }