obfs3.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /*
  2. * Copyright (c) 2014, 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 obfs3 provides an implementation of the Tor Project's obfs3
  28. // obfuscation protocol.
  29. package obfs3 // import "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/transports/obfs3"
  30. import (
  31. "bytes"
  32. "crypto/aes"
  33. "crypto/cipher"
  34. "crypto/hmac"
  35. "crypto/sha256"
  36. "errors"
  37. "io"
  38. "net"
  39. "time"
  40. pt "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/goptlib"
  41. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/common/csrand"
  42. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/common/uniformdh"
  43. "gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/lyrebird/transports/base"
  44. )
  45. const (
  46. transportName = "obfs3"
  47. clientHandshakeTimeout = time.Duration(30) * time.Second
  48. serverHandshakeTimeout = time.Duration(30) * time.Second
  49. initiatorKdfString = "Initiator obfuscated data"
  50. responderKdfString = "Responder obfuscated data"
  51. initiatorMagicString = "Initiator magic"
  52. responderMagicString = "Responder magic"
  53. maxPadding = 8194
  54. keyLen = 16
  55. )
  56. // Transport is the obfs3 implementation of the base.Transport interface.
  57. type Transport struct{}
  58. // Name returns the name of the obfs3 transport protocol.
  59. func (t *Transport) Name() string {
  60. return transportName
  61. }
  62. // ClientFactory returns a new obfs3ClientFactory instance.
  63. func (t *Transport) ClientFactory(stateDir string) (base.ClientFactory, error) {
  64. cf := &obfs3ClientFactory{transport: t}
  65. return cf, nil
  66. }
  67. // ServerFactory returns a new obfs3ServerFactory instance.
  68. func (t *Transport) ServerFactory(stateDir string, args *pt.Args) (base.ServerFactory, error) {
  69. sf := &obfs3ServerFactory{transport: t}
  70. return sf, nil
  71. }
  72. type obfs3ClientFactory struct {
  73. transport base.Transport
  74. }
  75. func (cf *obfs3ClientFactory) Transport() base.Transport {
  76. return cf.transport
  77. }
  78. func (cf *obfs3ClientFactory) ParseArgs(args *pt.Args) (interface{}, error) {
  79. return nil, nil
  80. }
  81. func (cf *obfs3ClientFactory) Dial(network, addr string, dialFn base.DialFunc, args interface{}) (net.Conn, error) {
  82. conn, err := dialFn(network, addr)
  83. if err != nil {
  84. return nil, err
  85. }
  86. dialConn := conn
  87. if conn, err = newObfs3ClientConn(conn); err != nil {
  88. dialConn.Close()
  89. return nil, err
  90. }
  91. return conn, nil
  92. }
  93. // Not yet implemented
  94. func (cf *obfs3ClientFactory) OnEvent(f func(base.TransportEvent)) {}
  95. type obfs3ServerFactory struct {
  96. transport base.Transport
  97. }
  98. func (sf *obfs3ServerFactory) Transport() base.Transport {
  99. return sf.transport
  100. }
  101. func (sf *obfs3ServerFactory) Args() *pt.Args {
  102. return nil
  103. }
  104. func (sf *obfs3ServerFactory) WrapConn(conn net.Conn) (net.Conn, error) {
  105. return newObfs3ServerConn(conn)
  106. }
  107. type obfs3Conn struct {
  108. net.Conn
  109. isInitiator bool
  110. rxMagic []byte
  111. txMagic []byte
  112. rxBuf *bytes.Buffer
  113. rx *cipher.StreamReader
  114. tx *cipher.StreamWriter
  115. }
  116. func newObfs3ClientConn(conn net.Conn) (c *obfs3Conn, err error) {
  117. // Initialize a client connection, and start the handshake timeout.
  118. c = &obfs3Conn{conn, true, nil, nil, new(bytes.Buffer), nil, nil}
  119. deadline := time.Now().Add(clientHandshakeTimeout)
  120. if err = c.SetDeadline(deadline); err != nil {
  121. return nil, err
  122. }
  123. // Handshake.
  124. if err = c.handshake(); err != nil {
  125. return nil, err
  126. }
  127. // Disarm the handshake timer.
  128. if err = c.SetDeadline(time.Time{}); err != nil {
  129. return nil, err
  130. }
  131. return
  132. }
  133. func newObfs3ServerConn(conn net.Conn) (c *obfs3Conn, err error) {
  134. // Initialize a server connection, and start the handshake timeout.
  135. c = &obfs3Conn{conn, false, nil, nil, new(bytes.Buffer), nil, nil}
  136. deadline := time.Now().Add(serverHandshakeTimeout)
  137. if err = c.SetDeadline(deadline); err != nil {
  138. return nil, err
  139. }
  140. // Handshake.
  141. if err = c.handshake(); err != nil {
  142. return nil, err
  143. }
  144. // Disarm the handshake timer.
  145. if err = c.SetDeadline(time.Time{}); err != nil {
  146. return nil, err
  147. }
  148. return
  149. }
  150. func (conn *obfs3Conn) handshake() error {
  151. // The party who opens the connection is the 'initiator'; the one who
  152. // accepts it is the 'responder'. Each begins by generating a
  153. // UniformDH keypair, and a random number PADLEN in [0, MAX_PADDING/2].
  154. // Both parties then send:
  155. //
  156. // PUB_KEY | WR(PADLEN)
  157. privateKey, err := uniformdh.GenerateKey(csrand.Reader)
  158. if err != nil {
  159. return err
  160. }
  161. padLen := csrand.IntRange(0, maxPadding/2)
  162. blob := make([]byte, uniformdh.Size+padLen)
  163. publicKey, err := privateKey.PublicKey.Bytes()
  164. if err != nil {
  165. return err
  166. }
  167. copy(blob[0:], publicKey)
  168. if err := csrand.Bytes(blob[uniformdh.Size:]); err != nil {
  169. return err
  170. }
  171. if _, err := conn.Conn.Write(blob); err != nil {
  172. return err
  173. }
  174. // Read the public key from the peer.
  175. rawPeerPublicKey := make([]byte, uniformdh.Size)
  176. if _, err := io.ReadFull(conn.Conn, rawPeerPublicKey); err != nil {
  177. return err
  178. }
  179. var peerPublicKey uniformdh.PublicKey
  180. if err := peerPublicKey.SetBytes(rawPeerPublicKey); err != nil {
  181. return err
  182. }
  183. // After retrieving the public key of the other end, each party
  184. // completes the DH key exchange and generates a shared-secret for the
  185. // session (named SHARED_SECRET).
  186. sharedSecret, err := uniformdh.Handshake(privateKey, &peerPublicKey)
  187. if err != nil {
  188. return err
  189. }
  190. if err := conn.kdf(sharedSecret); err != nil {
  191. return err
  192. }
  193. return nil
  194. }
  195. func (conn *obfs3Conn) kdf(sharedSecret []byte) error {
  196. // Using that shared-secret each party derives its encryption keys as
  197. // follows:
  198. //
  199. // INIT_SECRET = HMAC(SHARED_SECRET, "Initiator obfuscated data")
  200. // RESP_SECRET = HMAC(SHARED_SECRET, "Responder obfuscated data")
  201. // INIT_KEY = INIT_SECRET[:KEYLEN]
  202. // INIT_COUNTER = INIT_SECRET[KEYLEN:]
  203. // RESP_KEY = RESP_SECRET[:KEYLEN]
  204. // RESP_COUNTER = RESP_SECRET[KEYLEN:]
  205. initHmac := hmac.New(sha256.New, sharedSecret)
  206. _, _ = initHmac.Write([]byte(initiatorKdfString))
  207. initSecret := initHmac.Sum(nil)
  208. initHmac.Reset()
  209. _, _ = initHmac.Write([]byte(initiatorMagicString))
  210. initMagic := initHmac.Sum(nil)
  211. respHmac := hmac.New(sha256.New, sharedSecret)
  212. _, _ = respHmac.Write([]byte(responderKdfString))
  213. respSecret := respHmac.Sum(nil)
  214. respHmac.Reset()
  215. _, _ = respHmac.Write([]byte(responderMagicString))
  216. respMagic := respHmac.Sum(nil)
  217. // The INIT_KEY value keys a block cipher (in CTR mode) used to
  218. // encrypt values from initiator to responder thereafter. The counter
  219. // mode's initial counter value is INIT_COUNTER. The RESP_KEY value
  220. // keys a block cipher (in CTR mode) used to encrypt values from
  221. // responder to initiator thereafter. That counter mode's initial
  222. // counter value is RESP_COUNTER.
  223. //
  224. // Note: To have this be the last place where the shared secret is used,
  225. // also generate the magic value to send/scan for here.
  226. initBlock, err := aes.NewCipher(initSecret[:keyLen])
  227. if err != nil {
  228. return err
  229. }
  230. initStream := cipher.NewCTR(initBlock, initSecret[keyLen:])
  231. respBlock, err := aes.NewCipher(respSecret[:keyLen])
  232. if err != nil {
  233. return err
  234. }
  235. respStream := cipher.NewCTR(respBlock, respSecret[keyLen:])
  236. if conn.isInitiator {
  237. conn.tx = &cipher.StreamWriter{S: initStream, W: conn.Conn}
  238. conn.rx = &cipher.StreamReader{S: respStream, R: conn.rxBuf}
  239. conn.txMagic = initMagic
  240. conn.rxMagic = respMagic
  241. } else {
  242. conn.tx = &cipher.StreamWriter{S: respStream, W: conn.Conn}
  243. conn.rx = &cipher.StreamReader{S: initStream, R: conn.rxBuf}
  244. conn.txMagic = respMagic
  245. conn.rxMagic = initMagic
  246. }
  247. return nil
  248. }
  249. func (conn *obfs3Conn) findPeerMagic() error {
  250. var hsBuf [maxPadding + sha256.Size]byte
  251. for {
  252. n, err := conn.Conn.Read(hsBuf[:])
  253. if err != nil {
  254. // Yes, Read can return partial data and an error, but continuing
  255. // past that is nonsensical.
  256. return err
  257. }
  258. conn.rxBuf.Write(hsBuf[:n])
  259. pos := bytes.Index(conn.rxBuf.Bytes(), conn.rxMagic)
  260. if pos == -1 {
  261. if conn.rxBuf.Len() >= maxPadding+sha256.Size {
  262. return errors.New("failed to find peer magic value")
  263. }
  264. continue
  265. } else if pos > maxPadding {
  266. return errors.New("peer sent too much pre-magic-padding")
  267. }
  268. // Discard the padding/MAC.
  269. pos += len(conn.rxMagic)
  270. _ = conn.rxBuf.Next(pos)
  271. return nil
  272. }
  273. }
  274. func (conn *obfs3Conn) Read(b []byte) (n int, err error) {
  275. // If this is the first time we read data post handshake, scan for the
  276. // magic value.
  277. if conn.rxMagic != nil {
  278. if err = conn.findPeerMagic(); err != nil {
  279. conn.Close()
  280. return
  281. }
  282. conn.rxMagic = nil
  283. }
  284. // If the handshake receive buffer is still present...
  285. if conn.rxBuf != nil {
  286. // And it is empty...
  287. if conn.rxBuf.Len() == 0 {
  288. // There is no more trailing data left from the handshake process,
  289. // so rewire the cipher.StreamReader to pull data from the network
  290. // instead of the temporary receive buffer.
  291. conn.rx.R = conn.Conn
  292. conn.rxBuf = nil
  293. }
  294. }
  295. return conn.rx.Read(b)
  296. }
  297. func (conn *obfs3Conn) Write(b []byte) (n int, err error) {
  298. // If this is the first time we write data post handshake, send the
  299. // padding/magic value.
  300. if conn.txMagic != nil {
  301. padLen := csrand.IntRange(0, maxPadding/2)
  302. blob := make([]byte, padLen+len(conn.txMagic))
  303. if err = csrand.Bytes(blob[:padLen]); err != nil {
  304. conn.Close()
  305. return
  306. }
  307. copy(blob[padLen:], conn.txMagic)
  308. if _, err = conn.Conn.Write(blob); err != nil {
  309. conn.Close()
  310. return
  311. }
  312. conn.txMagic = nil
  313. }
  314. return conn.tx.Write(b)
  315. }
  316. var _ base.ClientFactory = (*obfs3ClientFactory)(nil)
  317. var _ base.ServerFactory = (*obfs3ServerFactory)(nil)
  318. var _ base.Transport = (*Transport)(nil)
  319. var _ net.Conn = (*obfs3Conn)(nil)