conn.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. /*
  2. * Copyright (c) 2015, Yawning Angel <yawning at schwanenlied dot me>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright notice,
  9. * this list of conditions and the following disclaimer.
  10. *
  11. * * Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  19. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  20. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  21. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  22. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  23. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  24. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25. * POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. package scramblesuit
  28. import (
  29. "bytes"
  30. "crypto/aes"
  31. "crypto/cipher"
  32. "crypto/hmac"
  33. "crypto/sha256"
  34. "encoding/base32"
  35. "encoding/binary"
  36. "errors"
  37. "fmt"
  38. "hash"
  39. "io"
  40. "net"
  41. "time"
  42. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
  43. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/common/csrand"
  44. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/common/drbg"
  45. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/common/probdist"
  46. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/common/uniformdh"
  47. )
  48. const (
  49. passwordArg = "password"
  50. maxSegmentLength = 1448
  51. maxPayloadLength = 1427
  52. sharedSecretLength = 160 / 8 // k_B
  53. clientHandshakeTimeout = time.Duration(60) * time.Second
  54. minLenDistLength = 21
  55. maxLenDistLength = maxSegmentLength
  56. keyLength = 32 + 8 + 32
  57. pktPrngSeedLength = 32
  58. pktOverhead = macLength + pktHdrLength
  59. pktHdrLength = 2 + 2 + 1
  60. pktPayload = 1
  61. pktNewTicket = 1 << 1
  62. pktPrngSeed = 1 << 2
  63. )
  64. var (
  65. // ErrNotSupported is the error returned for a unsupported operation.
  66. ErrNotSupported = errors.New("scramblesuit: operation not supported")
  67. // ErrInvalidPacket is the error returned when a invalid packet is received.
  68. ErrInvalidPacket = errors.New("scramblesuit: invalid packet")
  69. zeroPadBytes [maxPayloadLength]byte
  70. )
  71. type ssSharedSecret [sharedSecretLength]byte
  72. type ssClientArgs struct {
  73. kB *ssSharedSecret
  74. sessionKey *uniformdh.PrivateKey
  75. }
  76. func newClientArgs(args *pt.Args) (ca *ssClientArgs, err error) {
  77. ca = &ssClientArgs{}
  78. if ca.kB, err = parsePasswordArg(args); err != nil {
  79. return nil, err
  80. }
  81. // Generate the client keypair before opening a connection since the time
  82. // taken is visible to an adversary. This key might not end up being used
  83. // if a session ticket is present, but this doesn't take that long.
  84. if ca.sessionKey, err = uniformdh.GenerateKey(csrand.Reader); err != nil {
  85. return nil, err
  86. }
  87. return
  88. }
  89. func parsePasswordArg(args *pt.Args) (*ssSharedSecret, error) {
  90. str, ok := args.Get(passwordArg)
  91. if !ok {
  92. return nil, fmt.Errorf("missing argument '%s'", passwordArg)
  93. }
  94. // To match the obfsproxy behavior, 'str' should contain a Base32 encoded
  95. // shared secret (k_B) used for handshaking.
  96. decoded, err := base32.StdEncoding.DecodeString(str)
  97. if err != nil {
  98. return nil, fmt.Errorf("failed to decode password: %s", err)
  99. }
  100. if len(decoded) != sharedSecretLength {
  101. return nil, fmt.Errorf("password length %d is invalid", len(decoded))
  102. }
  103. ss := new(ssSharedSecret)
  104. copy(ss[:], decoded)
  105. return ss, nil
  106. }
  107. type ssCryptoState struct {
  108. s cipher.Stream
  109. mac hash.Hash
  110. }
  111. func newCryptoState(aesKey []byte, ivPrefix []byte, macKey []byte) (*ssCryptoState, error) {
  112. // The ScrambleSuit CTR-AES256 link crypto uses an 8 byte prefix from the
  113. // KDF, and a 64 bit counter initialized to 1 as the IV. The initial value
  114. // of the counter isn't documented in the spec either.
  115. var initialCtr = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}
  116. iv := make([]byte, 0, aes.BlockSize)
  117. iv = append(iv, ivPrefix...)
  118. iv = append(iv, initialCtr...)
  119. b, err := aes.NewCipher(aesKey)
  120. if err != nil {
  121. return nil, err
  122. }
  123. s := cipher.NewCTR(b, iv)
  124. mac := hmac.New(sha256.New, macKey)
  125. return &ssCryptoState{s: s, mac: mac}, nil
  126. }
  127. type ssConn struct {
  128. net.Conn
  129. isServer bool
  130. lenDist *probdist.WeightedDist
  131. receiveBuffer *bytes.Buffer
  132. receiveDecodedBuffer *bytes.Buffer
  133. receiveState ssRxState
  134. txCrypto *ssCryptoState
  135. rxCrypto *ssCryptoState
  136. ticketStore *ssTicketStore
  137. }
  138. type ssRxState struct {
  139. mac []byte
  140. hdr []byte
  141. totalLen int
  142. payloadLen int
  143. }
  144. func (conn *ssConn) Read(b []byte) (n int, err error) {
  145. // If the receive payload buffer is empty, consume data off the network.
  146. for conn.receiveDecodedBuffer.Len() == 0 {
  147. if err = conn.readPackets(); err != nil {
  148. break
  149. }
  150. }
  151. // Service the read request using buffered payload.
  152. if conn.receiveDecodedBuffer.Len() > 0 {
  153. n, _ = conn.receiveDecodedBuffer.Read(b)
  154. }
  155. return
  156. }
  157. func (conn *ssConn) Write(b []byte) (n int, err error) {
  158. var frameBuf bytes.Buffer
  159. p := b
  160. toSend := len(p)
  161. for toSend > 0 {
  162. // Send as much payload as will fit into each frame as possible.
  163. wrLen := len(p)
  164. if wrLen > maxPayloadLength {
  165. wrLen = maxPayloadLength
  166. }
  167. payload := p[:wrLen]
  168. if err = conn.makePacket(&frameBuf, pktPayload, payload, 0); err != nil {
  169. return 0, err
  170. }
  171. toSend -= wrLen
  172. p = p[wrLen:]
  173. n += wrLen
  174. }
  175. // Pad out the burst as appropriate.
  176. if err = conn.padBurst(&frameBuf, conn.lenDist.Sample()); err != nil {
  177. return 0, err
  178. }
  179. // Write and return.
  180. _, err = conn.Conn.Write(frameBuf.Bytes())
  181. return
  182. }
  183. func (conn *ssConn) SetDeadline(t time.Time) error {
  184. return ErrNotSupported
  185. }
  186. func (conn *ssConn) SetReadDeadline(t time.Time) error {
  187. return ErrNotSupported
  188. }
  189. func (conn *ssConn) SetWriteDeadline(t time.Time) error {
  190. return ErrNotSupported
  191. }
  192. func (conn *ssConn) makePacket(w io.Writer, pktType byte, data []byte, padLen int) error {
  193. payloadLen := len(data)
  194. totalLen := payloadLen + padLen
  195. if totalLen > maxPayloadLength {
  196. panic(fmt.Sprintf("BUG: makePacket() len(data) + padLen > maxPayloadLength: %d + %d > %d", len(data), padLen, maxPayloadLength))
  197. }
  198. // Build the packet header (total length, payload length, flags),
  199. // and append the payload and padding.
  200. pkt := make([]byte, pktHdrLength, pktHdrLength+payloadLen+padLen)
  201. binary.BigEndian.PutUint16(pkt[0:], uint16(totalLen))
  202. binary.BigEndian.PutUint16(pkt[2:], uint16(payloadLen))
  203. pkt[4] = pktType
  204. pkt = append(pkt, data...)
  205. pkt = append(pkt, zeroPadBytes[:padLen]...)
  206. // Encrypt the packet, and calculate the MAC.
  207. conn.txCrypto.s.XORKeyStream(pkt, pkt)
  208. conn.txCrypto.mac.Reset()
  209. _, _ = conn.txCrypto.mac.Write(pkt)
  210. mac := conn.txCrypto.mac.Sum(nil)[:macLength]
  211. // Write out MAC | Packet. Note that this does not go onto the network
  212. // yet, as w is a byte.Buffer (This is done so each call to conn.Write()
  213. // gets padding added).
  214. if _, err := w.Write(mac); err != nil {
  215. return err
  216. }
  217. _, err := w.Write(pkt)
  218. return err
  219. }
  220. func (conn *ssConn) readPackets() error {
  221. // Consume and buffer up to 1 MSS worth of data.
  222. var buf [maxSegmentLength]byte
  223. rdLen, rdErr := conn.Conn.Read(buf[:])
  224. conn.receiveBuffer.Write(buf[:rdLen])
  225. // Process incoming packets incrementally. conn.receiveState stores
  226. // the results of partial processing.
  227. for conn.receiveBuffer.Len() > 0 {
  228. if conn.receiveState.mac == nil {
  229. // Read and store the packet MAC.
  230. if conn.receiveBuffer.Len() < macLength {
  231. break
  232. }
  233. mac := make([]byte, macLength)
  234. _, _ = conn.receiveBuffer.Read(mac)
  235. conn.receiveState.mac = mac
  236. }
  237. if conn.receiveState.hdr == nil {
  238. // Read and store the packet header.
  239. if conn.receiveBuffer.Len() < pktHdrLength {
  240. break
  241. }
  242. hdr := make([]byte, pktHdrLength)
  243. _, _ = conn.receiveBuffer.Read(hdr)
  244. // Add the encrypted packet header to the HMAC instance, and then
  245. // decrypt it so that the length of the packet can be determined.
  246. conn.rxCrypto.mac.Reset()
  247. _, _ = conn.rxCrypto.mac.Write(hdr)
  248. conn.rxCrypto.s.XORKeyStream(hdr, hdr)
  249. // Store the plaintext packet header, and host byte order length
  250. // values.
  251. totalLen := int(binary.BigEndian.Uint16(hdr[0:]))
  252. payloadLen := int(binary.BigEndian.Uint16(hdr[2:]))
  253. if payloadLen > totalLen || totalLen > maxPayloadLength {
  254. return ErrInvalidPacket
  255. }
  256. conn.receiveState.hdr = hdr
  257. conn.receiveState.totalLen = totalLen
  258. conn.receiveState.payloadLen = payloadLen
  259. }
  260. var data []byte
  261. if conn.receiveState.totalLen > 0 {
  262. // If the packet actually has payload (including padding), read,
  263. // digest and decrypt it.
  264. if conn.receiveBuffer.Len() < conn.receiveState.totalLen {
  265. break
  266. }
  267. data = make([]byte, conn.receiveState.totalLen)
  268. _, _ = conn.receiveBuffer.Read(data)
  269. _, _ = conn.rxCrypto.mac.Write(data)
  270. conn.rxCrypto.s.XORKeyStream(data, data)
  271. }
  272. // Authenticate the packet, by comparing the received MAC with the one
  273. // calculated over the ciphertext consumed off the network.
  274. cmpMAC := conn.rxCrypto.mac.Sum(nil)[:macLength]
  275. if !hmac.Equal(cmpMAC, conn.receiveState.mac[:]) {
  276. return ErrInvalidPacket
  277. }
  278. // Based on the packet flags, do something useful with the payload.
  279. data = data[:conn.receiveState.payloadLen]
  280. switch conn.receiveState.hdr[4] {
  281. case pktPayload:
  282. // User data, write it into the decoded payload buffer so that Read
  283. // calls can be serviced.
  284. conn.receiveDecodedBuffer.Write(data)
  285. case pktNewTicket:
  286. // New Session Ticket to be used for future handshakes, store it in
  287. // the Session Ticket store.
  288. if conn.isServer || len(data) != ticketKeyLength+ticketLength {
  289. return ErrInvalidPacket
  290. }
  291. conn.ticketStore.storeTicket(conn.RemoteAddr(), data)
  292. case pktPrngSeed:
  293. // New PRNG_SEED for the protocol polymorphism. Regenerate the
  294. // length obfuscation probability distribution.
  295. if conn.isServer || len(data) != pktPrngSeedLength {
  296. return ErrInvalidPacket
  297. }
  298. seed, err := drbg.SeedFromBytes(data)
  299. if err != nil {
  300. return ErrInvalidPacket
  301. }
  302. conn.lenDist.Reset(seed)
  303. default:
  304. return ErrInvalidPacket
  305. }
  306. // Done processing a packet, clear the partial state.
  307. conn.receiveState.mac = nil
  308. conn.receiveState.hdr = nil
  309. conn.receiveState.totalLen = 0
  310. conn.receiveState.payloadLen = 0
  311. }
  312. return rdErr
  313. }
  314. func (conn *ssConn) clientHandshake(kB *ssSharedSecret, sessionKey *uniformdh.PrivateKey) error {
  315. if conn.isServer {
  316. return fmt.Errorf("clientHandshake called on server connection")
  317. }
  318. // Query the Session Ticket store to see if there is a stored session
  319. // ticket.
  320. ticket, err := conn.ticketStore.getTicket(conn.RemoteAddr())
  321. if err != nil {
  322. return err
  323. } else if ticket != nil {
  324. // Ok, there is an existing ticket, so attempt to do a Session Ticket
  325. // handshake. Until we write to the network, failures are non-fatal as
  326. // we can transition gracefully into doing a UniformDH handshake.
  327. // Derive the keys from the prestored master key received with the
  328. // ticket. This is done before the actual handshake since the
  329. // handshake uses the outgoing HMAC-SHA256-128 key for authentication.
  330. if err = conn.initCrypto(ticket.key[:]); err != nil {
  331. goto handshakeUDH
  332. }
  333. // Generate and send the ticket handshake. There is no response, since
  334. // both sides have the keying material.
  335. hs := newTicketClientHandshake(conn.txCrypto.mac, ticket)
  336. blob, err := hs.generateHandshake()
  337. if err != nil {
  338. goto handshakeUDH
  339. }
  340. if _, err = conn.Conn.Write(blob); err != nil {
  341. return err
  342. }
  343. return nil
  344. }
  345. handshakeUDH:
  346. // No session ticket, so take the slow path and do a UniformDH based
  347. // handshake.
  348. // Generate and send the client handshake.
  349. hs := newDHClientHandshake(kB, sessionKey)
  350. blob, err := hs.generateHandshake()
  351. if err != nil {
  352. return err
  353. }
  354. if _, err = conn.Conn.Write(blob); err != nil {
  355. return err
  356. }
  357. // Consume the server handshake. Since we don't actually know the length
  358. // of the respose, we need to consume data off the network till we either
  359. // find the tail marker + MAC digest indicating that a handshake response
  360. // has been received, or the maximum handshake size passes without a valid
  361. // response.
  362. var hsBuf [maxHandshakeLength]byte
  363. for {
  364. var n int
  365. if n, err = conn.Conn.Read(hsBuf[:]); err != nil {
  366. return err
  367. }
  368. conn.receiveBuffer.Write(hsBuf[:n])
  369. // Attempt to process all the data seen so far as a response.
  370. var seed []byte
  371. n, seed, err = hs.parseServerHandshake(conn.receiveBuffer.Bytes())
  372. if err == errMarkNotFoundYet {
  373. // No response found yet, keep trying.
  374. continue
  375. } else if err != nil {
  376. return err
  377. }
  378. // Ok, done processing the handshake, discard the response, and do the
  379. // key derivation based off the calculated shared secret.
  380. _ = conn.receiveBuffer.Next(n)
  381. err = conn.initCrypto(seed)
  382. return err
  383. }
  384. }
  385. func (conn *ssConn) initCrypto(seed []byte) error {
  386. // Use HKDF-SHA256 (Expand only, no Extract) to generate session keys from
  387. // initial keying material.
  388. okm := hkdfExpand(sha256.New, seed, nil, kdfSecretLength)
  389. var err error
  390. conn.txCrypto, err = newCryptoState(okm[0:32], okm[32:40], okm[80:112])
  391. if err != nil {
  392. return err
  393. }
  394. conn.rxCrypto, err = newCryptoState(okm[40:72], okm[72:80], okm[112:144])
  395. if err != nil {
  396. return err
  397. }
  398. return nil
  399. }
  400. func (conn *ssConn) padBurst(burst *bytes.Buffer, sampleLen int) error {
  401. // Burst contains the fully encrypted+MACed outgoing payload that will be
  402. // written to the network. Pad it out so that the last segment (based on
  403. // the ScrambleSuit MTU) is sampleLen bytes.
  404. dataLen := burst.Len() % maxSegmentLength
  405. padLen := 0
  406. if sampleLen >= dataLen {
  407. padLen = sampleLen - dataLen
  408. } else {
  409. padLen = (maxSegmentLength - dataLen) + sampleLen
  410. }
  411. if padLen < pktOverhead {
  412. // The padLen is less than the MAC + packet header in length, so
  413. // two packets are required.
  414. padLen += maxSegmentLength
  415. }
  416. if padLen == 0 {
  417. return nil
  418. }
  419. if padLen > maxSegmentLength {
  420. // Note: packetmorpher.py: getPadding is slightly wrong and only
  421. // accounts for one of the two packet headers.
  422. if err := conn.makePacket(burst, pktPayload, nil, 700-pktOverhead); err != nil {
  423. return err
  424. }
  425. return conn.makePacket(burst, pktPayload, nil, padLen-(700+2*pktOverhead))
  426. }
  427. return conn.makePacket(burst, pktPayload, nil, padLen-pktOverhead)
  428. }
  429. func newScrambleSuitClientConn(conn net.Conn, tStore *ssTicketStore, ca *ssClientArgs) (net.Conn, error) {
  430. // At this point we have kB and our session key, so we can directly
  431. // start handshaking and seeing what happens.
  432. // Seed the initial polymorphism distribution.
  433. seed, err := drbg.NewSeed()
  434. if err != nil {
  435. return nil, err
  436. }
  437. dist := probdist.New(seed, minLenDistLength, maxLenDistLength, true)
  438. // Allocate the client structure.
  439. c := &ssConn{conn, false, dist, bytes.NewBuffer(nil), bytes.NewBuffer(nil), ssRxState{}, nil, nil, tStore}
  440. // Start the handshake timeout.
  441. deadline := time.Now().Add(clientHandshakeTimeout)
  442. if err := conn.SetDeadline(deadline); err != nil {
  443. return nil, err
  444. }
  445. // Attempt to handshake.
  446. if err := c.clientHandshake(ca.kB, ca.sessionKey); err != nil {
  447. return nil, err
  448. }
  449. // Stop the handshake timeout.
  450. if err := conn.SetDeadline(time.Time{}); err != nil {
  451. return nil, err
  452. }
  453. return c, nil
  454. }