session.go 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525
  1. /*
  2. * Copyright (c) 2023, Psiphon Inc.
  3. * All rights reserved.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. package inproxy
  20. import (
  21. "bytes"
  22. "context"
  23. "crypto/rand"
  24. "math"
  25. "sync"
  26. "time"
  27. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
  28. lrucache "github.com/cognusion/go-cache-lru"
  29. "github.com/flynn/noise"
  30. "golang.org/x/crypto/curve25519"
  31. "golang.zx2c4.com/wireguard/replay"
  32. )
  33. const (
  34. sessionsTTL = 5 * time.Minute
  35. sessionsMaxSize = 100000
  36. sessionObfuscationPaddingMinSize = 0
  37. sessionObfuscationPaddingMaxSize = 256
  38. )
  39. const (
  40. SessionProtocolName = "psiphon-inproxy-session"
  41. SessionProtocolVersion1 = 1
  42. )
  43. // SessionPrologue is a Noise protocol prologue, which binds the session ID to
  44. // the session.
  45. type SessionPrologue struct {
  46. SessionProtocolName string `cbor:"1,keyasint,omitempty"`
  47. SessionProtocolVersion uint32 `cbor:"2,keyasint,omitempty"`
  48. SessionID ID `cbor:"3,keyasint,omitempty"`
  49. }
  50. // SessionPacket is a Noise protocol message, which may be a session handshake
  51. // message, or secured application data, a SessionRoundTrip.
  52. type SessionPacket struct {
  53. SessionID ID `cbor:"1,keyasint,omitempty"`
  54. Nonce uint64 `cbor:"2,keyasint,omitempty"`
  55. Payload []byte `cbor:"3,keyasint,omitempty"`
  56. }
  57. // SessionRoundTrip is an application data request or response, which is
  58. // secured by the Noise protocol session. Each request is assigned a unique
  59. // RoundTripID, and each corresponding response has the same RoundTripID.
  60. type SessionRoundTrip struct {
  61. RoundTripID ID `cbor:"1,keyasint,omitempty"`
  62. Payload []byte `cbor:"2,keyasint,omitempty"`
  63. }
  64. // SessionPrivateKey is a Noise protocol private key.
  65. type SessionPrivateKey [32]byte
  66. // SessionPublicKey is a Noise protocol private key.
  67. type SessionPublicKey [32]byte
  68. // IsZero indicates if the private key is zero-value.
  69. func (k SessionPrivateKey) IsZero() bool {
  70. var zero SessionPrivateKey
  71. return bytes.Equal(k[:], zero[:])
  72. }
  73. // GenerateSessionPrivateKey creates a new Noise protocol session private key
  74. // using crypto/rand.
  75. func GenerateSessionPrivateKey() (SessionPrivateKey, error) {
  76. var privateKey SessionPrivateKey
  77. keyPair, err := noise.DH25519.GenerateKeypair(rand.Reader)
  78. if err != nil {
  79. return privateKey, errors.Trace(err)
  80. }
  81. if len(keyPair.Private) != len(privateKey) {
  82. return privateKey, errors.TraceNew("unexpected private key length")
  83. }
  84. copy(privateKey[:], keyPair.Private)
  85. return privateKey, nil
  86. }
  87. // GetSessionPublicKey returns the public key corresponding to the private
  88. // key.
  89. func GetSessionPublicKey(privateKey SessionPrivateKey) (SessionPublicKey, error) {
  90. var sessionPublicKey SessionPublicKey
  91. publicKey, err := curve25519.X25519(privateKey[:], curve25519.Basepoint)
  92. if err != nil {
  93. return sessionPublicKey, errors.Trace(err)
  94. }
  95. if len(publicKey) != len(sessionPublicKey) {
  96. return sessionPublicKey, errors.TraceNew("unexpected public key length")
  97. }
  98. copy(sessionPublicKey[:], publicKey)
  99. return sessionPublicKey, nil
  100. }
  101. // InitiatorSessions is a set of secure Noise protocol sessions for an
  102. // initiator. For in-proxy, clients and proxies will initiate sessions with
  103. // one more brokers and brokers will initiate sessions with multiple Psiphon
  104. // servers.
  105. //
  106. // Secure sessions provide encryption, authentication of the responder,
  107. // identity hiding for the initiator, forward secrecy, and anti-replay for
  108. // application data.
  109. //
  110. // Maintaining a set of established sessions minimizes round trips and
  111. // overhead, as established sessions can be shared and reused for many client
  112. // requests to one broker or many broker requests to one server.
  113. //
  114. // Currently, InitiatorSessions doesn't not cap the number of sessions or use
  115. // an LRU cache since the number of peers is bounded in the in-proxy
  116. // architecture; clients will typically use one or no more than a handful of
  117. // brokers and brokers will exchange requests with a subset of Psiphon
  118. // servers bounded by the in-proxy capability.
  119. //
  120. // InitiatorSessions are used via the RoundTrip function or InitiatorRoundTrip
  121. // type. RoundTrip is a synchronous function which performs any necessary
  122. // session establishment handshake along with the request/response exchange.
  123. // InitiatorRoundTrip offers an iterator interface, with stepwise invocations
  124. // for each step of the handshake and round trip.
  125. //
  126. // All round trips attempt to share and reuse any existing, established
  127. // session to a given peer. For a given peer, the waitToShareSession option
  128. // determines whether round trips will block and wait if a session handshake
  129. // is already in progress, or proceed with a concurrent handshake. For
  130. // in-proxy, clients and proxies use waitToShareSession; as broker/server
  131. // round trips are relayed through clients, brokers do not use
  132. // waitToShareSession so as to not rely on any single client.
  133. //
  134. // Round trips can be performed concurrently and requests can arrive out-of-
  135. // order. The higher level transport for sessions is responsible for
  136. // multiplexing round trips and maintaining the association between a request
  137. // and it's corresponding response.
  138. type InitiatorSessions struct {
  139. privateKey SessionPrivateKey
  140. mutex sync.Mutex
  141. sessions sessionLookup
  142. }
  143. // NewInitiatorSessions creates a new InitiatorSessions with the specified
  144. // initator private key.
  145. func NewInitiatorSessions(
  146. initiatorPrivateKey SessionPrivateKey) *InitiatorSessions {
  147. return &InitiatorSessions{
  148. privateKey: initiatorPrivateKey,
  149. sessions: make(sessionLookup),
  150. }
  151. }
  152. // RoundTrip sends the request to the specified responder and returns the
  153. // response.
  154. //
  155. // RoundTrip will establish a session when required, or reuse an existing
  156. // session when available.
  157. //
  158. // When waitToShareSession is true, RoundTrip will block until an existing,
  159. // non-established session is available to be shared.
  160. //
  161. // RoundTrip returns immediately when ctx becomes done.
  162. func (s *InitiatorSessions) RoundTrip(
  163. ctx context.Context,
  164. roundTripper RoundTripper,
  165. responderPublicKey SessionPublicKey,
  166. responderRootObfuscationSecret ObfuscationSecret,
  167. waitToShareSession bool,
  168. request []byte) ([]byte, error) {
  169. rt, err := s.NewRoundTrip(
  170. responderPublicKey,
  171. responderRootObfuscationSecret,
  172. waitToShareSession,
  173. request)
  174. if err != nil {
  175. return nil, errors.Trace(err)
  176. }
  177. didResetSession := false
  178. var in []byte
  179. for {
  180. out, err := rt.Next(ctx, in)
  181. if err != nil {
  182. return nil, errors.Trace(err)
  183. }
  184. if out == nil {
  185. response, err := rt.Response()
  186. if err != nil {
  187. return nil, errors.Trace(err)
  188. }
  189. return response, nil
  190. }
  191. in, err = roundTripper.RoundTrip(ctx, out)
  192. if err != nil {
  193. // Perform at most one session reset, to accomodate the expected
  194. // case where the initator reuses an established session that is
  195. // expired for the responder.
  196. //
  197. // Higher levels implicitly provide additional retries to cover
  198. // other cases; Psiphon client tunnel establishment will retry
  199. // in-proxy dials; the proxy will retry its announce request if
  200. // it fails -- after an appropriate delay.
  201. if didResetSession == false {
  202. // TODO: log reset
  203. rt.ResetSession()
  204. didResetSession = true
  205. } else {
  206. return nil, errors.Trace(err)
  207. }
  208. }
  209. }
  210. }
  211. // NewRoundTrip creates a new InitiatorRoundTrip which will perform a
  212. // request/response round trip with the specified responder, sending the
  213. // input request. The InitiatorRoundTrip will establish a session when
  214. // required, or reuse an existing session when available.
  215. //
  216. // When waitToShareSession is true, InitiatorRoundTrip.Next will block until
  217. // an existing, non-established session is available to be shared.
  218. //
  219. // NewRoundTrip does not block or perform any session operations; the
  220. // operations begin on the first InitiatorRoundTrip.Next call. The content of
  221. // request should not be modified after calling NewRoundTrip.
  222. func (s *InitiatorSessions) NewRoundTrip(
  223. responderPublicKey SessionPublicKey,
  224. responderRootObfuscationSecret ObfuscationSecret,
  225. waitToShareSession bool,
  226. request []byte) (*InitiatorRoundTrip, error) {
  227. s.mutex.Lock()
  228. defer s.mutex.Unlock()
  229. // Generate a new round trip ID for the session round trip. The response
  230. // is expected to echo back the same round trip ID. This check detects
  231. // any potential misrouting of multiplexed round trip exchanges.
  232. roundTripID, err := MakeID()
  233. if err != nil {
  234. return nil, errors.Trace(err)
  235. }
  236. requestPayload, err := marshalRecord(
  237. SessionRoundTrip{RoundTripID: roundTripID, Payload: request},
  238. recordTypeSessionRoundTrip)
  239. if err != nil {
  240. return nil, errors.Trace(err)
  241. }
  242. return &InitiatorRoundTrip{
  243. initiatorSessions: s,
  244. responderPublicKey: responderPublicKey,
  245. responderRootObfuscationSecret: responderRootObfuscationSecret,
  246. waitToShareSession: waitToShareSession,
  247. roundTripID: roundTripID,
  248. requestPayload: requestPayload,
  249. }, nil
  250. }
  251. // getSession looks for an existing session for the peer specified by public
  252. // key. When none is found, newSession is called to create a new session, and
  253. // this is stored, associated with the key. If an existing session is found,
  254. // indicate if it is ready to be shared or not.
  255. func (s *InitiatorSessions) getSession(
  256. publicKey SessionPublicKey,
  257. newSession func() (*session, error)) (
  258. retSession *session, retisNew bool, retIsReady bool, retErr error) {
  259. s.mutex.Lock()
  260. defer s.mutex.Unlock()
  261. session, ok := s.sessions[publicKey]
  262. if ok {
  263. return session, false, session.isReadyToShare(nil), nil
  264. }
  265. session, err := newSession()
  266. if err != nil {
  267. return nil, false, false, errors.Trace(err)
  268. }
  269. s.sessions[publicKey] = session
  270. return session, true, session.isReadyToShare(nil), nil
  271. }
  272. // setSession sets the session associated with the peer's public key.
  273. func (s *InitiatorSessions) setSession(publicKey SessionPublicKey, session *session) {
  274. s.mutex.Lock()
  275. defer s.mutex.Unlock()
  276. s.sessions[publicKey] = session
  277. }
  278. // removeIfSession removes the session associated with the peer's public key,
  279. // if it's the specified session.
  280. func (s *InitiatorSessions) removeIfSession(publicKey SessionPublicKey, session *session) {
  281. s.mutex.Lock()
  282. defer s.mutex.Unlock()
  283. currentSession, ok := s.sessions[publicKey]
  284. if !ok || session != currentSession {
  285. return
  286. }
  287. delete(s.sessions, publicKey)
  288. }
  289. // InitiatorRoundTrip represents the state of a session round trip, including
  290. // a session handshake if required. The session handshake and round trip is
  291. // advanced by calling InitiatorRoundTrip.Next.
  292. type InitiatorRoundTrip struct {
  293. initiatorSessions *InitiatorSessions
  294. responderPublicKey SessionPublicKey
  295. responderRootObfuscationSecret ObfuscationSecret
  296. waitToShareSession bool
  297. roundTripID ID
  298. requestPayload []byte
  299. mutex sync.Mutex
  300. sharingSession bool
  301. didResetSession bool
  302. session *session
  303. response []byte
  304. }
  305. // ResetSession clears the InitiatorRoundTrip session. Call ResetSession when
  306. // the responder indicates an error in response to session packet. Errors are
  307. // sent at the transport level. An error is expected when the initator reuses
  308. // an established session that is expired for the responder. After calling
  309. // ResetSession, the following Next call will being establishing a new
  310. // session. The expected session expiry scenario should occur at most once
  311. // per round trip.
  312. //
  313. // Limitation: since session errors/failures are handled at the transport
  314. // level, they may be forged, depending on the security provided by the
  315. // transport layer. For client and proxy sessions with a broker, if domain
  316. // fronting is used then security depends on the HTTPS layer and CDNs can
  317. // forge a session error. For broker sessions with Psiphon servers, the
  318. // relaying client could forge a server error -- but that would deny service
  319. // to the client when the BrokerServerRequest fails.
  320. //
  321. // ResetSession is ignored if response already received or if ResetSession
  322. // already called before.
  323. //
  324. // Higher levels implicitly provide additional round trip retries to cover
  325. // other cases; Psiphon client tunnel establishment will retry in-proxy
  326. // dials; the proxy will retry its announce request if it fails -- after an
  327. // appropriate delay.
  328. func (r *InitiatorRoundTrip) ResetSession() {
  329. r.mutex.Lock()
  330. defer r.mutex.Unlock()
  331. if r.didResetSession || r.response != nil {
  332. return
  333. }
  334. if r.session != nil {
  335. r.initiatorSessions.removeIfSession(r.responderPublicKey, r.session)
  336. r.didResetSession = true
  337. r.session = nil
  338. }
  339. }
  340. // Next advances a round trip, as well as any session handshake that may be
  341. // first required. Next takes the next packet received from the responder and
  342. // returns the next packet to send to the responder. To begin, pass a nil
  343. // receivedPacket. The round trip is complete when Next returns nil for the
  344. // next packet to send; the response can be fetched from
  345. // InitiatorRoundTrip.Response.
  346. //
  347. // When waitToShareSession is set, Next will block until an existing,
  348. // non-established session is available to be shared.
  349. //
  350. // Multiple concurrent round trips are supported and requests from different
  351. // round trips can arrive at the responder out-of-order. The provided
  352. // transport is responsible for multiplexing round trips and maintaining an
  353. // association between sent and received packets for a given round trip.
  354. //
  355. // Next returns immediately when ctx becomes done.
  356. func (r *InitiatorRoundTrip) Next(
  357. ctx context.Context,
  358. receivedPacket []byte) (retSendPacket []byte, retErr error) {
  359. r.mutex.Lock()
  360. defer r.mutex.Unlock()
  361. if ctx != nil {
  362. err := ctx.Err()
  363. if err != nil {
  364. return nil, errors.Trace(err)
  365. }
  366. }
  367. if r.session == nil {
  368. // If the session is nil, this is the first call to Next, and no
  369. // packet from the peer is expected.
  370. if receivedPacket != nil {
  371. return nil, errors.TraceNew("unexpected received packet")
  372. }
  373. newSession := func() (*session, error) {
  374. session, err := newSession(
  375. true, // isInitiator
  376. r.initiatorSessions.privateKey,
  377. r.responderRootObfuscationSecret,
  378. nil, // No obfuscation replay history
  379. &r.responderPublicKey,
  380. r.requestPayload,
  381. nil,
  382. nil)
  383. if err != nil {
  384. return nil, errors.Trace(err)
  385. }
  386. return session, nil
  387. }
  388. // Check for an existing session, or create a new one if there's no
  389. // existing session.
  390. //
  391. // To ensure the concurrent waitToShareSession cases don't start
  392. // multiple handshakes, getSession populates the initiatorSessions
  393. // session map with a new, unestablished session.
  394. session, isNew, isReady, err := r.initiatorSessions.getSession(
  395. r.responderPublicKey, newSession)
  396. if err != nil {
  397. return nil, errors.Trace(err)
  398. }
  399. if isNew {
  400. // When isNew is true, this InitiatorRoundTrip owns the session
  401. // and will perform the handshake.
  402. r.session = session
  403. r.sharingSession = false
  404. } else {
  405. if isReady {
  406. // When isReady is true, this shared session is fully
  407. // established and ready for immediate use.
  408. r.session = session
  409. r.sharingSession = true
  410. } else {
  411. // The existing session is not yet ready for use.
  412. if r.waitToShareSession {
  413. // Wait for the owning InitiatorRoundTrip to complete the
  414. // session handshake and then share the session.
  415. signal := make(chan struct{})
  416. if !session.isReadyToShare(signal) {
  417. select {
  418. case <-signal:
  419. case <-ctx.Done():
  420. return nil, errors.Trace(ctx.Err())
  421. }
  422. }
  423. r.session = session
  424. r.sharingSession = true
  425. } else {
  426. // Don't wait: create a new, unshared session.
  427. r.session, err = newSession()
  428. if err != nil {
  429. return nil, errors.Trace(err)
  430. }
  431. r.sharingSession = false
  432. }
  433. }
  434. }
  435. if r.sharingSession {
  436. // The shared session was either ready for immediate use, or we
  437. // waited. Send the round trip request payload.
  438. sendPacket, err := r.session.sendPacket(r.requestPayload)
  439. if err != nil {
  440. return nil, errors.Trace(err)
  441. }
  442. return sendPacket, nil
  443. }
  444. // Begin the handshake for a new session.
  445. _, sendPacket, _, err := r.session.nextHandshakePacket(nil)
  446. if err != nil {
  447. return nil, errors.Trace(err)
  448. }
  449. return sendPacket, nil
  450. }
  451. // Not the first Next call, so a packet from the peer is expected.
  452. if receivedPacket == nil {
  453. return nil, errors.TraceNew("missing received packet")
  454. }
  455. if r.sharingSession || r.session.isEstablished() {
  456. // When sharing an established and ready session, or once an owned
  457. // session is eastablished, the next packet is post-handshake and
  458. // should be the round trip request response.
  459. responsePayload, err := r.session.receivePacket(receivedPacket)
  460. if err != nil {
  461. return nil, errors.Trace(err)
  462. }
  463. var sessionRoundTrip SessionRoundTrip
  464. err = unmarshalRecord(recordTypeSessionRoundTrip, responsePayload, &sessionRoundTrip)
  465. if err != nil {
  466. return nil, errors.Trace(err)
  467. }
  468. // Check that the response RoundTripID matches the request RoundTripID.
  469. if sessionRoundTrip.RoundTripID != r.roundTripID {
  470. return nil, errors.TraceNew("unexpected round trip ID")
  471. }
  472. // Store the response so it can be retrieved later.
  473. r.response = sessionRoundTrip.Payload
  474. return nil, nil
  475. }
  476. // Continue the handshake. Since the first payload is sent to the
  477. // responder along with the initiator's last handshake message, there's
  478. // no sendPacket call in the owned session case. The last
  479. // nextHandshakePacket will bundle it. Also, the payload output of
  480. // nextHandshakePacket is ignored, as only a responder will receive a
  481. // payload in a handshake message.
  482. isEstablished, sendPacket, _, err := r.session.nextHandshakePacket(receivedPacket)
  483. if err != nil {
  484. return nil, errors.Trace(err)
  485. }
  486. if isEstablished {
  487. // Retain the most recently established session as the cached session
  488. // for reuse. This should be a no-op in the isNew case and only have
  489. // an effect for !inNew and !waitToShareSession. Modifying the
  490. // initiatorSessions map entry should not impact any concurrent
  491. // handshakes, as each InitiatorRoundTrip maintains its own reference
  492. // to its session.
  493. r.initiatorSessions.setSession(r.responderPublicKey, r.session)
  494. }
  495. return sendPacket, nil
  496. }
  497. // Response returns the round trip response. Call Response after Next returns
  498. // nil for the next packet to send, indicating that the round trip is
  499. // complete.
  500. func (r *InitiatorRoundTrip) Response() ([]byte, error) {
  501. r.mutex.Lock()
  502. defer r.mutex.Unlock()
  503. if r.response == nil {
  504. return nil, errors.TraceNew("no response")
  505. }
  506. return r.response, nil
  507. }
  508. // ResponderSessions is a set of secure Noise protocol sessions for an
  509. // responder. For in-proxy, brokers respond to clients and proxies and
  510. // servers respond to brokers.
  511. //
  512. // Secure sessions provide encryption, authentication of the responder,
  513. // identity hiding for the initiator, forward secrecy, and anti-replay for
  514. // application data.
  515. //
  516. // ResponderSessions maintains a cache of established sessions to minimizes
  517. // round trips and overhead as initiators are expected to make multiple round
  518. // trips. The cache has a TTL and maximum size with LRU to cap overall memory
  519. // usage. A broker may receive requests from millions of clients and proxies
  520. // and so only more recent sessions will be retained. Servers will receive
  521. // requests from only a handful of brokers, and so the TTL is not applied.
  522. //
  523. // Multiple, concurrent sessions for a single initiator public key are
  524. // supported.
  525. type ResponderSessions struct {
  526. privateKey SessionPrivateKey
  527. rootObfuscationSecret ObfuscationSecret
  528. applyTTL bool
  529. obfuscationReplayHistory *obfuscationReplayHistory
  530. expectedInitiatorPublicKeys sessionPublicKeyLookup
  531. mutex sync.Mutex
  532. sessions *lrucache.Cache
  533. }
  534. // NewResponderSessions creates a new ResponderSessions which allows any
  535. // initiators to establish a session. A TTL is applied to cached sessions.
  536. func NewResponderSessions(
  537. responderPrivateKey SessionPrivateKey,
  538. responderRootObfuscationSecret ObfuscationSecret) (*ResponderSessions, error) {
  539. return &ResponderSessions{
  540. privateKey: responderPrivateKey,
  541. rootObfuscationSecret: responderRootObfuscationSecret,
  542. applyTTL: true,
  543. obfuscationReplayHistory: newObfuscationReplayHistory(),
  544. sessions: lrucache.NewWithLRU(sessionsTTL, 1*time.Minute, sessionsMaxSize),
  545. }, nil
  546. }
  547. // NewResponderSessionsForKnownInitiators creates a new ResponderSessions
  548. // which allows only allow-listed initiators to establish a session. No TTL
  549. // is applied to cached sessions.
  550. //
  551. // The NewResponderSessionsForKnownInitiators configuration is for Psiphon
  552. // servers responding to brokers. Only a handful of brokers are expected to
  553. // be deployed. A relatively small allow list of expected broker public keys
  554. // is easy to manage, deploy, and update. No TTL is applied to keep the
  555. // sessions established as much as possible and avoid extra client-relayed
  556. // round trips for BrokerServerRequests.
  557. func NewResponderSessionsForKnownInitiators(
  558. responderPrivateKey SessionPrivateKey,
  559. responderRootObfuscationKey ObfuscationSecret,
  560. initiatorPublicKeys []SessionPublicKey) (*ResponderSessions, error) {
  561. s, err := NewResponderSessions(responderPrivateKey, responderRootObfuscationKey)
  562. if err != nil {
  563. return nil, errors.Trace(err)
  564. }
  565. expectedPublicKeys := make(sessionPublicKeyLookup)
  566. for _, publicKey := range initiatorPublicKeys {
  567. expectedPublicKeys[publicKey] = struct{}{}
  568. }
  569. s.expectedInitiatorPublicKeys = expectedPublicKeys
  570. return s, nil
  571. }
  572. // RequestHandler is an application-level handler that receives the decrypted
  573. // request payload and returns a response payload to be encrypted and sent to
  574. // the initiator. The initiatorID is the authenticated identifier of the
  575. // initiator: client, proxy, or broker.
  576. type RequestHandler func(initiatorID ID, request []byte) ([]byte, error)
  577. // HandlePacket takes a session packet, as received at the transport level,
  578. // and handles session handshake and request decryption. While a session
  579. // handshakes, HandlePacket returns the next handshake message to be relayed
  580. // back to the initiator over the transport.
  581. //
  582. // Once a session is fully established and a request is decrypted, the inner
  583. // request payload is passed to the RequestHandler for application-level
  584. // processing. The response received from the RequestHandler will be
  585. // encrypted with the session and returned from HandlePacket as the next
  586. // packet to send back over the transport.
  587. //
  588. // The session packet contains a session ID that is used to route packets from
  589. // many initiators to the correct session state.
  590. //
  591. // Above the Noise protocol security layer, session packets have an
  592. // obfuscation layer. If a packet doesn't authenticate with the expected
  593. // obfuscation secret, or if a packet is replayed, HandlePacket returns an
  594. // error. The obfuscation anti-replay layer covers replays of Noise handshake
  595. // messages which aren't covered by the Noise nonce anti-replay. When
  596. // HandlePacket returns an error, the caller should invoke anti-probing
  597. // behavior, such as returning a generic 404 error from an HTTP server for
  598. // HTTPS transports.
  599. //
  600. // There is one expected error case with legitimate initiators: when an
  601. // initiator reuses a session that is expired or no longer in the responder
  602. // cache. In this case the error response should be the same; the initiator
  603. // knows to attempt one session re-establishment in this case.
  604. //
  605. // The HandlePacket caller should implement initiator rate limiting in its
  606. // transport level.
  607. func (s *ResponderSessions) HandlePacket(
  608. inPacket []byte,
  609. requestHandler RequestHandler) (retOutPacket []byte, retErr error) {
  610. // Concurrency: no locks are held for this function, only in specific
  611. // helper functions.
  612. // unwrapSessionPacket deobfuscates the session packet, and unmarshals a
  613. // SessionPacket. The SessionPacket.SessionID is used to route the
  614. // session packet to an existing session or to create a new one. The
  615. // SessionPacket.Payload is a Noise handshake message or an encrypted
  616. // request and that will be handled below.
  617. sessionPacket, err := unwrapSessionPacket(
  618. s.rootObfuscationSecret, false, s.obfuscationReplayHistory, inPacket)
  619. if err != nil {
  620. return nil, errors.Trace(err)
  621. }
  622. sessionID := sessionPacket.SessionID
  623. // Check for an existing session with this session ID, or create a new one
  624. // if not found. If the session _was_ in the cache but is now expired, a
  625. // new session is created, but subsequent Noise operations will fail.
  626. session, err := s.getSession(sessionID)
  627. if err != nil {
  628. return nil, errors.Trace(err)
  629. }
  630. defer func() {
  631. if retErr != nil {
  632. // If an error is returned, the session has failed, so don't
  633. // retain it in the cache as it could be more recently used than
  634. // an older but still valid session.
  635. //
  636. // TODO: should we retain the session if it has completed the
  637. // handshake? As with initiator error signals, and depending on
  638. // the transport security level, a SessionPacket with a
  639. // legitimate session ID but corrupt Noise payload could be
  640. // forged, terminating a legitimate session.
  641. s.removeSession(sessionID)
  642. }
  643. }()
  644. var requestPayload []byte
  645. if session.isEstablished() {
  646. // When the session is already established, decrypt the packet to get
  647. // the request.
  648. payload, err := session.receiveUnmarshaledPacket(sessionPacket)
  649. if err != nil {
  650. return nil, errors.Trace(err)
  651. }
  652. requestPayload = payload
  653. } else {
  654. // When the session is not established, the packet is the next
  655. // handshake message. The initiator appends the request payload to
  656. // the end of its last XK handshake message, and in that case payload
  657. // will contain the request.
  658. isEstablished, outPacket, payload, err :=
  659. session.nextUnmarshaledHandshakePacket(sessionPacket)
  660. if err != nil {
  661. return nil, errors.Trace(err)
  662. }
  663. if outPacket != nil {
  664. // The handshake is not complete until outPacket is nil; send the
  665. // next handshake packet.
  666. if payload != nil {
  667. // A payload is not expected unless the handshake is complete.
  668. return nil, errors.TraceNew("unexpected handshake payload")
  669. }
  670. // The session TTL is not extended here. Initiators, including
  671. // clients and proxies, are given sessionsTTL to complete the
  672. // entire handshake.
  673. return outPacket, nil
  674. }
  675. if !isEstablished || payload == nil {
  676. // When outPacket is nil, the handshake should be complete --
  677. // isEstablished -- and, by convention, the first request payload
  678. // should be available.
  679. return nil, errors.TraceNew("unexpected established state")
  680. }
  681. requestPayload = payload
  682. }
  683. // Extend the session TTL.
  684. s.touchSession(sessionID, session)
  685. initiatorID, err := session.getPeerID()
  686. if err != nil {
  687. return nil, errors.Trace(err)
  688. }
  689. var sessionRoundTrip SessionRoundTrip
  690. err = unmarshalRecord(recordTypeSessionRoundTrip, requestPayload, &sessionRoundTrip)
  691. if err != nil {
  692. return nil, errors.Trace(err)
  693. }
  694. request := sessionRoundTrip.Payload
  695. response, err := requestHandler(initiatorID, request)
  696. if err != nil {
  697. return nil, errors.Trace(err)
  698. }
  699. // The response is assigned the same RoundTripID as the request.
  700. sessionRoundTrip = SessionRoundTrip{
  701. RoundTripID: sessionRoundTrip.RoundTripID,
  702. Payload: response,
  703. }
  704. responsePayload, err := marshalRecord(
  705. sessionRoundTrip, recordTypeSessionRoundTrip)
  706. if err != nil {
  707. return nil, errors.Trace(err)
  708. }
  709. responsePacket, err := session.sendPacket(responsePayload)
  710. if err != nil {
  711. return nil, errors.Trace(err)
  712. }
  713. return responsePacket, nil
  714. }
  715. // touchSession sets a cached session for the specified session ID; if the
  716. // session is already in the cache, its TTL is extended. The LRU session
  717. // cache entry may be discarded once the cache is full.
  718. func (s *ResponderSessions) touchSession(sessionID ID, session *session) {
  719. s.mutex.Lock()
  720. defer s.mutex.Unlock()
  721. TTL := lrucache.DefaultExpiration
  722. if !s.applyTTL {
  723. TTL = lrucache.NoExpiration
  724. }
  725. s.sessions.Set(string(sessionID[:]), session, TTL)
  726. }
  727. // getSession returns an existing session for the specified session ID, or
  728. // creates a new session, and places it in the cache, if not found.
  729. func (s *ResponderSessions) getSession(sessionID ID) (*session, error) {
  730. s.mutex.Lock()
  731. defer s.mutex.Unlock()
  732. strSessionID := string(sessionID[:])
  733. entry, ok := s.sessions.Get(strSessionID)
  734. if ok {
  735. return entry.(*session), nil
  736. }
  737. session, err := newSession(
  738. false, // !isInitiator
  739. s.privateKey,
  740. s.rootObfuscationSecret,
  741. s.obfuscationReplayHistory,
  742. nil,
  743. nil,
  744. &sessionID,
  745. s.expectedInitiatorPublicKeys)
  746. if err != nil {
  747. return nil, errors.Trace(err)
  748. }
  749. s.sessions.Set(
  750. strSessionID, session, lrucache.DefaultExpiration)
  751. return session, nil
  752. }
  753. // removeSession removes any existing session for the specified session ID.
  754. func (s *ResponderSessions) removeSession(sessionID ID) {
  755. s.mutex.Lock()
  756. defer s.mutex.Unlock()
  757. s.sessions.Delete(string(sessionID[:]))
  758. }
  759. type sessionState int
  760. const (
  761. /*
  762. XK:
  763. <- s
  764. ...
  765. -> e, es
  766. <- e, ee
  767. -> s, se [+ first payload]
  768. */
  769. sessionStateInitiator_XK_send_e_es = iota
  770. sessionStateInitiator_XK_recv_e_ee_send_s_se_payload
  771. sessionStateInitiator_XK_established
  772. sessionStateResponder_XK_recv_e_es_send_e_ee
  773. sessionStateResponder_XK_recv_s_se_payload
  774. sessionStateResponder_XK_established
  775. )
  776. type sessionPublicKeyLookup map[SessionPublicKey]struct{}
  777. type sessionLookup map[SessionPublicKey]*session
  778. // session represents a Noise protocol session, including its initial
  779. // handshake state.
  780. //
  781. // The XK pattern is used:
  782. // - Initiators may have short-lived static keys (clients), or long-lived
  783. // static keys (proxies and brokers). The initiator key is securely
  784. // transmitted to the responder while hiding its value.
  785. // - The responder static key is always known (K) and exchanged out of
  786. // band.
  787. // - Provides forward secrecy.
  788. // - The round trip request can be appended to the initiators final
  789. // handshake message, eliminating an extra round trip.
  790. //
  791. // For in-proxy, any client or proxy can connect to a broker. Only allowed
  792. // brokers can connect to a server.
  793. //
  794. // To limit access to allowed brokers, expectedInitiatorPublicKeys is an allow
  795. // list of broker public keys. XK is still used for this case, instead of
  796. // KK:
  797. // - With KK, the broker identity would have to be known before the Noise
  798. // handshake begins
  799. // - With XK, the broker proves possession of a private key corresponding to
  800. // a broker public key on the allow list.
  801. // - While KK will abort sooner than XK when an invalid broker key is used,
  802. // completing the handshake and decrypting the first payload does not
  803. // leak any information.
  804. //
  805. // The is no "close" operation for sessions. Responders will maintain a cache
  806. // of established sessions and discard the state for expired sessions or in
  807. // an LRU fashion. Initiators will reuse sessions until they are rejected by
  808. // a responder.
  809. //
  810. // There is no state for the obfuscation layer; each packet is obfuscated
  811. // independently since session packets may arrive at a peer out-of-order.
  812. type session struct {
  813. isInitiator bool
  814. sessionID ID
  815. rootObfuscationSecret ObfuscationSecret
  816. replayHistory *obfuscationReplayHistory
  817. expectedInitiatorPublicKeys sessionPublicKeyLookup
  818. mutex sync.Mutex
  819. state sessionState
  820. signalOnEstablished []chan struct{}
  821. handshake *noise.HandshakeState
  822. firstPayload []byte
  823. peerPublicKey []byte
  824. send *noise.CipherState
  825. receive *noise.CipherState
  826. nonceReplay replay.Filter
  827. }
  828. func newSession(
  829. isInitiator bool,
  830. privateKey SessionPrivateKey,
  831. rootObfuscationSecret ObfuscationSecret,
  832. replayHistory *obfuscationReplayHistory,
  833. // Initiator
  834. expectedResponderPublicKey *SessionPublicKey,
  835. firstPayload []byte,
  836. // Responder
  837. peerSessionID *ID,
  838. expectedInitiatorPublicKeys sessionPublicKeyLookup) (*session, error) {
  839. if isInitiator {
  840. if peerSessionID != nil ||
  841. expectedResponderPublicKey == nil ||
  842. expectedInitiatorPublicKeys != nil ||
  843. firstPayload == nil {
  844. return nil, errors.TraceNew("unexpected initiator parameters")
  845. }
  846. } else {
  847. if peerSessionID == nil ||
  848. expectedResponderPublicKey != nil ||
  849. firstPayload != nil {
  850. return nil, errors.TraceNew("unexpected responder parameters")
  851. }
  852. }
  853. sessionID := peerSessionID
  854. if sessionID == nil {
  855. ID, err := MakeID()
  856. if err != nil {
  857. return nil, errors.Trace(err)
  858. }
  859. sessionID = &ID
  860. }
  861. // The prologue binds the session ID and other meta data to the session.
  862. prologue, err := cborEncoding.Marshal(SessionPrologue{
  863. SessionProtocolName: SessionProtocolName,
  864. SessionProtocolVersion: SessionProtocolVersion1,
  865. SessionID: *sessionID,
  866. })
  867. if err != nil {
  868. return nil, errors.Trace(err)
  869. }
  870. publicKey, err := GetSessionPublicKey(privateKey)
  871. if err != nil {
  872. return nil, errors.Trace(err)
  873. }
  874. // SessionProtocolVersion1 implies this ciphersuite
  875. config := noise.Config{
  876. CipherSuite: noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashBLAKE2b),
  877. Pattern: noise.HandshakeXK,
  878. Initiator: isInitiator,
  879. Prologue: prologue,
  880. StaticKeypair: noise.DHKey{
  881. Public: publicKey[:],
  882. Private: privateKey[:]},
  883. }
  884. if expectedResponderPublicKey != nil {
  885. config.PeerStatic = (*expectedResponderPublicKey)[:]
  886. }
  887. handshake, err := noise.NewHandshakeState(config)
  888. if err != nil {
  889. return nil, errors.Trace(err)
  890. }
  891. var state sessionState
  892. if isInitiator {
  893. state = sessionStateInitiator_XK_send_e_es
  894. } else {
  895. state = sessionStateResponder_XK_recv_e_es_send_e_ee
  896. }
  897. return &session{
  898. isInitiator: isInitiator,
  899. sessionID: *sessionID,
  900. rootObfuscationSecret: rootObfuscationSecret,
  901. replayHistory: replayHistory,
  902. expectedInitiatorPublicKeys: expectedInitiatorPublicKeys,
  903. state: state,
  904. signalOnEstablished: make([]chan struct{}, 0), // must be non-nil
  905. handshake: handshake,
  906. firstPayload: firstPayload,
  907. }, nil
  908. }
  909. // isEstablished indicates that the session handshake is complete.
  910. //
  911. // A session may not be ready to share when isEstablished is true.
  912. func (s *session) isEstablished() bool {
  913. s.mutex.Lock()
  914. defer s.mutex.Unlock()
  915. return s.handshake == nil
  916. }
  917. // isReadyToShare indicates that the session handshake is complete _and_ that
  918. // the peer is known to have received and processed the final handshake
  919. // message.
  920. //
  921. // When isReadyToShare is true, multiple round trips can use a session
  922. // concurrently. Requests from different round trips can arrive at the peer
  923. // out-of-order.
  924. //
  925. // Session sharing is performed by initiators, and in the XK handshake the
  926. // last step is the initiator sends a final message to the responder. While
  927. // the initiator session becomes "established" after that last message is
  928. // output, we need to delay other round trips from sharing the session and
  929. // sending session-encrypted packets to the responder before the responder
  930. // actually receives that final handshake message.
  931. //
  932. // isReadyToShare becomes true once the round trip performing the handshake
  933. // receives its round trip response, which demonstrates that the responder
  934. // received the final message.
  935. func (s *session) isReadyToShare(signal chan struct{}) bool {
  936. s.mutex.Lock()
  937. defer s.mutex.Unlock()
  938. if !s.isInitiator {
  939. return false
  940. }
  941. if s.handshake == nil && s.signalOnEstablished == nil {
  942. return true
  943. }
  944. if signal != nil {
  945. s.signalOnEstablished = append(
  946. s.signalOnEstablished, signal)
  947. }
  948. return false
  949. }
  950. // getPeerID returns the peer's public key, in the form of an ID. A given peer
  951. // identifier can only be provided by the peer with the corresponding private
  952. // key.
  953. func (s *session) getPeerID() (ID, error) {
  954. s.mutex.Lock()
  955. defer s.mutex.Unlock()
  956. var peerID ID
  957. if s.handshake != nil {
  958. return peerID, errors.TraceNew("not established")
  959. }
  960. if len(s.peerPublicKey) != len(peerID) {
  961. return peerID, errors.TraceNew("invalid peer public key")
  962. }
  963. copy(peerID[:], s.peerPublicKey)
  964. return peerID, nil
  965. }
  966. // sendPacket prepares a session packet to be sent to the peer, containing the
  967. // specified round trip payload. The packet is secured by the established
  968. // session.
  969. func (s *session) sendPacket(payload []byte) ([]byte, error) {
  970. s.mutex.Lock()
  971. defer s.mutex.Unlock()
  972. if s.handshake != nil {
  973. return nil, errors.TraceNew("not established")
  974. }
  975. if s.send == nil {
  976. return nil, errors.Trace(s.unexpectedStateError())
  977. }
  978. nonce := s.send.Nonce()
  979. // Unlike tunnels, for example, sessions are not for bulk data transfer
  980. // and we don't aim for zero allocation or extensive buffer reuse.
  981. encryptedPayload, err := s.send.Encrypt(nil, nil, payload)
  982. if err != nil {
  983. return nil, errors.Trace(err)
  984. }
  985. sessionPacket, err := s.wrapPacket(
  986. &SessionPacket{
  987. SessionID: s.sessionID,
  988. Nonce: nonce,
  989. Payload: encryptedPayload,
  990. })
  991. if err != nil {
  992. return nil, errors.Trace(err)
  993. }
  994. return sessionPacket, nil
  995. }
  996. // receivePacket opens a session packet received from the peer, using the
  997. // established session, and returns the round trip payload.
  998. //
  999. // As responders need to inspect the packet and use its session ID to route
  1000. // packets to the correct session, responders will call
  1001. // receiveUnmarshaledPacket instead.
  1002. func (s *session) receivePacket(packet []byte) ([]byte, error) {
  1003. sessionPacket, err := s.unwrapPacket(packet)
  1004. if err != nil {
  1005. return nil, errors.Trace(err)
  1006. }
  1007. payload, err := s.receiveUnmarshaledPacket(sessionPacket)
  1008. if err != nil {
  1009. return nil, errors.Trace(err)
  1010. }
  1011. return payload, nil
  1012. }
  1013. func (s *session) receiveUnmarshaledPacket(
  1014. sessionPacket *SessionPacket) ([]byte, error) {
  1015. s.mutex.Lock()
  1016. defer s.mutex.Unlock()
  1017. if s.receive == nil {
  1018. return nil, errors.Trace(s.unexpectedStateError())
  1019. }
  1020. if sessionPacket.SessionID != s.sessionID {
  1021. return nil, errors.Tracef("unexpected sessionID")
  1022. }
  1023. s.receive.SetNonce(sessionPacket.Nonce)
  1024. payload, err := s.receive.Decrypt(nil, nil, sessionPacket.Payload)
  1025. if err != nil {
  1026. return nil, errors.Trace(err)
  1027. }
  1028. if !s.nonceReplay.ValidateCounter(sessionPacket.Nonce, math.MaxUint64) {
  1029. return nil, errors.TraceNew("replay detected")
  1030. }
  1031. // The session is ready to share once it's received a post-handshake
  1032. // response from the peer.
  1033. s.readyToShare()
  1034. return payload, nil
  1035. }
  1036. // nextHandshakePacket advances the session handshake. nextHandshakePacket
  1037. // takes the next handshake packet received from the peer and returns the
  1038. // next handshake packet to send to the peer. Start by passing nil for
  1039. // inPacket. The handshake is complete when outPacket is nil.
  1040. //
  1041. // XK bundles the first initiator request payload along with a handshake
  1042. // message, and nextHandshakePacket output that payload to the responder when
  1043. // the handshake is complete.
  1044. //
  1045. // Once the handshake is complete, further round trips are exchanged using
  1046. // sendPacket and receivePacket.
  1047. //
  1048. // As responders need to inspect the packet and use its session ID to route
  1049. // packets to the correct session, responders will call
  1050. // nextUnmarshaledHandshakePacket instead.
  1051. func (s *session) nextHandshakePacket(inPacket []byte) (
  1052. isEstablished bool, outPacket []byte, payload []byte, err error) {
  1053. var sessionPacket *SessionPacket
  1054. if inPacket != nil {
  1055. sessionPacket, err = s.unwrapPacket(inPacket)
  1056. if err != nil {
  1057. return false, nil, nil, errors.Trace(err)
  1058. }
  1059. }
  1060. isEstablished, outPacket, payload, err =
  1061. s.nextUnmarshaledHandshakePacket(sessionPacket)
  1062. if err != nil {
  1063. return false, nil, nil, errors.Trace(err)
  1064. }
  1065. return isEstablished, outPacket, payload, nil
  1066. }
  1067. func (s *session) nextUnmarshaledHandshakePacket(sessionPacket *SessionPacket) (
  1068. isEstablished bool, outPacket []byte, payload []byte, err error) {
  1069. s.mutex.Lock()
  1070. defer s.mutex.Unlock()
  1071. var in []byte
  1072. if sessionPacket != nil {
  1073. if sessionPacket.SessionID != s.sessionID {
  1074. return false, nil, nil, errors.Tracef("unexpected sessionID")
  1075. }
  1076. if sessionPacket.Nonce != 0 {
  1077. return false, nil, nil, errors.TraceNew("unexpected nonce")
  1078. }
  1079. in = sessionPacket.Payload
  1080. }
  1081. // Handle handshake state transitions.
  1082. switch s.state {
  1083. // Initiator
  1084. case sessionStateInitiator_XK_send_e_es:
  1085. out, _, _, err := s.handshake.WriteMessage(nil, nil)
  1086. if err != nil {
  1087. return false, nil, nil, errors.Trace(err)
  1088. }
  1089. outPacket, err := s.wrapPacket(
  1090. &SessionPacket{SessionID: s.sessionID, Payload: out})
  1091. if err != nil {
  1092. return false, nil, nil, errors.Trace(err)
  1093. }
  1094. s.state = sessionStateInitiator_XK_recv_e_ee_send_s_se_payload
  1095. return false, outPacket, nil, nil
  1096. case sessionStateInitiator_XK_recv_e_ee_send_s_se_payload:
  1097. _, _, _, err := s.handshake.ReadMessage(nil, in)
  1098. if err != nil {
  1099. return false, nil, nil, errors.Trace(err)
  1100. }
  1101. out, send, receive, err := s.handshake.WriteMessage(nil, s.firstPayload)
  1102. if err != nil {
  1103. return false, nil, nil, errors.Trace(err)
  1104. }
  1105. outPacket, err := s.wrapPacket(
  1106. &SessionPacket{SessionID: s.sessionID, Payload: out})
  1107. if err != nil {
  1108. return false, nil, nil, errors.Trace(err)
  1109. }
  1110. s.state = sessionStateInitiator_XK_established
  1111. s.established(send, receive)
  1112. return true, outPacket, nil, nil
  1113. // Responder
  1114. case sessionStateResponder_XK_recv_e_es_send_e_ee:
  1115. _, _, _, err := s.handshake.ReadMessage(nil, in)
  1116. if err != nil {
  1117. return false, nil, nil, errors.Trace(err)
  1118. }
  1119. out, _, _, err := s.handshake.WriteMessage(nil, nil)
  1120. if err != nil {
  1121. return false, nil, nil, errors.Trace(err)
  1122. }
  1123. outPacket, err := s.wrapPacket(
  1124. &SessionPacket{SessionID: s.sessionID, Payload: out})
  1125. if err != nil {
  1126. return false, nil, nil, errors.Trace(err)
  1127. }
  1128. s.state = sessionStateResponder_XK_recv_s_se_payload
  1129. return false, outPacket, nil, nil
  1130. case sessionStateResponder_XK_recv_s_se_payload:
  1131. firstPayload, receive, send, err := s.handshake.ReadMessage(nil, in)
  1132. if err != nil {
  1133. return false, nil, nil, errors.Trace(err)
  1134. }
  1135. // Check if the initiator's public key in on the allow list.
  1136. //
  1137. // Limitation: unlike with the KK pattern, the handshake completes and
  1138. // the initial payload is decrypted even when the initiator public
  1139. // key is not on the allow list.
  1140. err = s.checkExpectedInitiatorPublicKeys(s.handshake.PeerStatic())
  1141. if err != nil {
  1142. return false, nil, nil, errors.Trace(err)
  1143. }
  1144. s.state = sessionStateResponder_XK_established
  1145. s.established(send, receive)
  1146. return true, nil, firstPayload, nil
  1147. }
  1148. return false, nil, nil, errors.Trace(s.unexpectedStateError())
  1149. }
  1150. func (s *session) checkExpectedInitiatorPublicKeys(peerPublicKey []byte) error {
  1151. if s.expectedInitiatorPublicKeys == nil {
  1152. return nil
  1153. }
  1154. var publicKey SessionPublicKey
  1155. copy(publicKey[:], peerPublicKey)
  1156. _, ok := s.expectedInitiatorPublicKeys[publicKey]
  1157. if !ok {
  1158. return errors.TraceNew("unexpected initiator public key")
  1159. }
  1160. return nil
  1161. }
  1162. // Set the session as established.
  1163. func (s *session) established(
  1164. send *noise.CipherState,
  1165. receive *noise.CipherState) {
  1166. // Assumes s.mutex lock is held.
  1167. s.peerPublicKey = s.handshake.PeerStatic()
  1168. s.handshake = nil
  1169. s.firstPayload = nil
  1170. s.send = send
  1171. s.receive = receive
  1172. }
  1173. // Set the session as ready to share.
  1174. func (s *session) readyToShare() {
  1175. // Assumes s.mutex lock is held.
  1176. if s.signalOnEstablished == nil {
  1177. return
  1178. }
  1179. for _, signal := range s.signalOnEstablished {
  1180. close(signal)
  1181. }
  1182. s.signalOnEstablished = nil
  1183. }
  1184. // Marshal and obfuscate a SessionPacket.
  1185. func (s *session) wrapPacket(sessionPacket *SessionPacket) ([]byte, error) {
  1186. // No lock. References only static session fields.
  1187. marshaledPacket, err := marshalRecord(
  1188. sessionPacket, recordTypeSessionPacket)
  1189. if err != nil {
  1190. return nil, errors.Trace(err)
  1191. }
  1192. obfuscatedPacket, err := obfuscateSessionPacket(
  1193. s.rootObfuscationSecret,
  1194. s.isInitiator,
  1195. marshaledPacket,
  1196. sessionObfuscationPaddingMinSize,
  1197. sessionObfuscationPaddingMaxSize)
  1198. if err != nil {
  1199. return nil, errors.Trace(err)
  1200. }
  1201. return obfuscatedPacket, nil
  1202. }
  1203. // Deobfuscate and unmarshal a SessionPacket.
  1204. func (s *session) unwrapPacket(obfuscatedPacket []byte) (*SessionPacket, error) {
  1205. // No lock. References only static session fields.
  1206. sessionPacket, err := unwrapSessionPacket(
  1207. s.rootObfuscationSecret,
  1208. s.isInitiator,
  1209. s.replayHistory,
  1210. obfuscatedPacket)
  1211. if err != nil {
  1212. return nil, errors.Trace(err)
  1213. }
  1214. return sessionPacket, nil
  1215. }
  1216. // Deobfuscate and unmarshal SessionPacket. unwrapSessionPacket is used by
  1217. // responders, which must peak at the SessionPacket and get the session ID to
  1218. // route packets to the correct session.
  1219. func unwrapSessionPacket(
  1220. rootObfuscationSecret ObfuscationSecret,
  1221. isInitiator bool,
  1222. replayHistory *obfuscationReplayHistory,
  1223. obfuscatedPacket []byte) (*SessionPacket, error) {
  1224. packet, err := deobfuscateSessionPacket(
  1225. rootObfuscationSecret,
  1226. isInitiator,
  1227. replayHistory,
  1228. obfuscatedPacket)
  1229. if err != nil {
  1230. return nil, errors.Trace(err)
  1231. }
  1232. var sessionPacket *SessionPacket
  1233. err = unmarshalRecord(recordTypeSessionPacket, packet, &sessionPacket)
  1234. if err != nil {
  1235. return nil, errors.Trace(err)
  1236. }
  1237. return sessionPacket, nil
  1238. }
  1239. // Create an error that includes the current handshake state.
  1240. func (s *session) unexpectedStateError() error {
  1241. s.mutex.Lock()
  1242. defer s.mutex.Unlock()
  1243. return errors.Tracef("unexpected state: %v", s.state)
  1244. }