secure_protocol_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. package aerotun
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "errors"
  6. "net/netip"
  7. "sync"
  8. "testing"
  9. "time"
  10. )
  11. func secureConfigs(t testing.TB) (TunnelInstance, TunnelInstance) {
  12. t.Helper()
  13. privA, pubA, err := GenerateIdentity()
  14. if err != nil {
  15. t.Fatal(err)
  16. }
  17. privB, pubB, err := GenerateIdentity()
  18. if err != nil {
  19. t.Fatal(err)
  20. }
  21. a := TunnelInstance{Protocol: 3, Mode: "client", PSK: testPSK, PrivateKey: privA, PublicKey: pubA, PeerPublicKey: pubB, Name: "atest0", LocalAddress: "10.99.0.2/32", PeerAddress: "10.99.0.1/32", AllowedIPs: []string{"10.99.0.1/32"}, RemoteEndpoint: "192.0.2.1:51830", MTU: 1420}
  22. b := a
  23. b.Mode = "server"
  24. b.PrivateKey = privB
  25. b.PublicKey = pubB
  26. b.PeerPublicKey = pubA
  27. b.LocalAddress, b.PeerAddress = a.PeerAddress, a.LocalAddress
  28. b.AllowedIPs = []string{"10.99.0.2/32"}
  29. b.RemoteEndpoint = ""
  30. return a, b
  31. }
  32. func securePair(t testing.TB) (*secureProtocol, *secureProtocol) {
  33. t.Helper()
  34. a, b := secureConfigs(t)
  35. pa, err := newSecureProtocol(a)
  36. if err != nil {
  37. t.Fatal(err)
  38. }
  39. pb, err := newSecureProtocol(b)
  40. if err != nil {
  41. t.Fatal(err)
  42. }
  43. return pa, pb
  44. }
  45. func secureEstablish(t testing.TB, a, b *secureProtocol) {
  46. t.Helper()
  47. b.mu.Lock()
  48. b.lastRequest = time.Time{}
  49. b.mu.Unlock()
  50. hello, err := a.initiation(1420, true)
  51. if err != nil || len(hello) == 0 {
  52. t.Fatalf("initiation: %v", err)
  53. }
  54. challenge, _, err := b.handleHandshake(hello, 1420)
  55. if err != nil || challenge[3] != secureCookie {
  56. t.Fatal("cookie challenge failed", err)
  57. }
  58. request, _, err := a.handleHandshake(challenge, 1420)
  59. if err != nil {
  60. t.Fatal(err)
  61. }
  62. response, _, err := b.handleHandshake(request, 1420)
  63. if err != nil {
  64. t.Fatal(err)
  65. }
  66. if _, mtu, err := a.handleHandshake(response, 1420); err != nil || mtu != 1420 {
  67. t.Fatalf("response %v %d", err, mtu)
  68. }
  69. var buf [128]byte
  70. var plain [128]byte
  71. var txNonce, rxNonce [24]byte
  72. packet, err := a.sealInto(buf[:0], &txNonce, FlagKeepalive, []byte{5, 140})
  73. if err != nil {
  74. t.Fatal(err)
  75. }
  76. if _, _, mtu, err := b.openInto(plain[:0], &rxNonce, packet); err != nil || (mtu != 1420 && mtu != 0) {
  77. t.Fatalf("confirmation: %v %d", err, mtu)
  78. }
  79. }
  80. func TestSecureHandshakeReplayPinsAndRekey(t *testing.T) {
  81. a, b := securePair(t)
  82. secureEstablish(t, a, b)
  83. var txBuf, rxBuf [2048]byte
  84. var tn, rn [24]byte
  85. raw := []byte("authenticated application payload")
  86. packet, err := a.sealInto(txBuf[:0], &tn, 0, raw)
  87. if err != nil {
  88. t.Fatal(err)
  89. }
  90. oldPacket := append([]byte(nil), packet...)
  91. forged := append([]byte(nil), packet...)
  92. binary.BigEndian.PutUint64(forged[8:16], 1<<40)
  93. if _, _, _, err = b.openInto(rxBuf[:0], &rn, forged); err == nil {
  94. t.Fatal("forged high counter accepted")
  95. }
  96. got, _, _, err := b.openInto(rxBuf[:0], &rn, packet)
  97. if err != nil || !bytes.Equal(got, raw) {
  98. t.Fatal("valid packet lost after forgery", err)
  99. }
  100. if _, _, _, err = b.openInto(rxBuf[:0], &rn, packet); !errors.Is(err, errReplay) {
  101. t.Fatalf("replay accepted: %v", err)
  102. }
  103. if _, _, _, err = a.openInto(rxBuf[:0], &rn, packet); err == nil {
  104. t.Fatal("reflected packet accepted")
  105. }
  106. oldSession := a.sessions.Load().current
  107. secureEstablish(t, a, b)
  108. if a.sessions.Load().current == oldSession || a.sessions.Load().current.txPrefix == oldSession.txPrefix {
  109. t.Fatal("rekey reused data key/nonce context")
  110. }
  111. if _, _, _, err = b.openInto(rxBuf[:0], &rn, oldPacket); !errors.Is(err, errReplay) {
  112. t.Fatal("old duplicate accepted during grace", err)
  113. }
  114. oldB := b.sessions.Load()
  115. b.sessions.Store(&secureSessions{current: oldB.current, previous: oldB.previous, previousUntil: time.Now().Add(-time.Second)})
  116. if _, _, _, err = b.openInto(rxBuf[:0], &rn, oldPacket); err == nil {
  117. t.Fatal("expired session accepted")
  118. }
  119. // An independent boot has fresh ephemeral keys and rejects old recordings.
  120. restarted, err := newSecureProtocol(b.cfg)
  121. if err != nil {
  122. t.Fatal(err)
  123. }
  124. if _, _, _, err = restarted.openInto(rxBuf[:0], &rn, oldPacket); err == nil {
  125. t.Fatal("old packet survived receiver restart")
  126. }
  127. secureEstablish(t, a, restarted)
  128. }
  129. func TestSecureWrongPeerAndWrongPSK(t *testing.T) {
  130. a, b := securePair(t)
  131. _, wrongPub, err := GenerateIdentity()
  132. if err != nil {
  133. t.Fatal(err)
  134. }
  135. b.peer, _ = decodeKey(wrongPub)
  136. packet, err := a.initiation(1420, true)
  137. if err != nil {
  138. t.Fatal(err)
  139. }
  140. challenge, _, err := b.handleHandshake(packet, 1420)
  141. if err != nil {
  142. t.Fatal(err)
  143. }
  144. request, _, err := a.handleHandshake(challenge, 1420)
  145. if err != nil {
  146. t.Fatal(err)
  147. }
  148. if _, _, err = b.handleHandshake(request, 1420); err == nil {
  149. t.Fatal("unpinned peer accepted with correct PSK")
  150. }
  151. a, b = securePair(t)
  152. b.psk = bytes.Repeat([]byte{42}, 32)
  153. packet, _ = a.initiation(1420, true)
  154. if _, _, err = b.handleHandshake(packet, 1420); err == nil {
  155. t.Fatal("wrong PSK accepted")
  156. }
  157. }
  158. func TestSecureDuplicateInitiationDoesNotActivateSession(t *testing.T) {
  159. a, b := securePair(t)
  160. init, _ := a.initiation(1420, true)
  161. challenge, _, err := b.handleHandshake(init, 1420)
  162. if err != nil {
  163. t.Fatal(err)
  164. }
  165. request, _, err := a.handleHandshake(challenge, 1420)
  166. if err != nil {
  167. t.Fatal(err)
  168. }
  169. response, _, err := b.handleHandshake(request, 1420)
  170. if err != nil {
  171. t.Fatal(err)
  172. }
  173. if b.sessions.Load().current != nil {
  174. t.Fatal("responder activated before key confirmation")
  175. }
  176. if _, _, err = b.handleHandshake(request, 1420); !errors.Is(err, errHandshakeRate) {
  177. t.Fatal("no handshake rate limit")
  178. }
  179. b.lastRequest = time.Now().Add(-2 * time.Second)
  180. again, _, err := b.handleHandshake(request, 1420)
  181. if err != nil || !bytes.Equal(response, again) {
  182. t.Fatal("retry regenerated keys", err)
  183. }
  184. }
  185. func TestSecureConcurrentCounters(t *testing.T) {
  186. a, b := securePair(t)
  187. secureEstablish(t, a, b)
  188. var wg sync.WaitGroup
  189. counts := make(chan uint64, 400)
  190. for range 4 {
  191. wg.Add(1)
  192. go func() {
  193. defer wg.Done()
  194. var buf [128]byte
  195. var nonce [24]byte
  196. for range 100 {
  197. out, err := a.sealInto(buf[:0], &nonce, 0, []byte("data"))
  198. if err != nil {
  199. t.Error(err)
  200. return
  201. }
  202. counts <- binary.BigEndian.Uint64(out[8:16])
  203. }
  204. }()
  205. }
  206. wg.Wait()
  207. close(counts)
  208. seen := map[uint64]bool{}
  209. for n := range counts {
  210. if seen[n] {
  211. t.Fatal("nonce counter reused")
  212. }
  213. seen[n] = true
  214. }
  215. }
  216. func TestSecureReplayReordering(t *testing.T) {
  217. var r secureReplay
  218. for _, n := range []uint64{1, 1024, 2, 1023, 2048, 2047} {
  219. if !r.accept(n) {
  220. t.Fatal("valid reordered packet rejected", n)
  221. }
  222. }
  223. for _, n := range []uint64{0, 1, 2, 1024, 2047, 2048} {
  224. if r.accept(n) {
  225. t.Fatal("old/duplicate accepted", n)
  226. }
  227. }
  228. }
  229. func BenchmarkSecureProtocolRoundTrip(b *testing.B) {
  230. a, peer := securePair(b)
  231. secureEstablish(b, a, peer)
  232. tx := make([]byte, 1500)
  233. rx := make([]byte, 1500)
  234. payload := make([]byte, 1200)
  235. var tn, rn [24]byte
  236. b.SetBytes(1200)
  237. b.ReportAllocs()
  238. b.ResetTimer()
  239. for range b.N {
  240. packet, err := a.sealInto(tx[:0], &tn, 0, payload)
  241. if err != nil {
  242. b.Fatal(err)
  243. }
  244. if _, _, _, err = peer.openInto(rx[:0], &rn, packet); err != nil {
  245. b.Fatal(err)
  246. }
  247. }
  248. }
  249. func FuzzSecurePacket(f *testing.F) {
  250. a, b := securePair(f)
  251. secureEstablish(f, a, b)
  252. f.Add([]byte("invalid"))
  253. var wire [128]byte
  254. var nonce [24]byte
  255. valid, _ := a.sealInto(wire[:0], &nonce, 0, []byte("payload"))
  256. f.Add(append([]byte(nil), valid...))
  257. f.Fuzz(func(t *testing.T, packet []byte) {
  258. var dst [2048]byte
  259. var n [24]byte
  260. _, _, _, _ = b.openInto(dst[:0], &n, packet)
  261. _, _, _ = b.handleHandshake(packet, 1420)
  262. })
  263. }
  264. func TestSecureInPlaceSealAndSourcePolicy(t *testing.T) {
  265. a, b := securePair(t)
  266. secureEstablish(t, a, b)
  267. wire := make([]byte, 1500)
  268. payload := wire[16:1216]
  269. for i := range payload {
  270. payload[i] = byte(i)
  271. }
  272. expected := append([]byte(nil), payload...)
  273. var tn, rn [24]byte
  274. var plain [1500]byte
  275. packet, err := a.sealInto(wire[:0], &tn, 0, payload)
  276. if err != nil {
  277. t.Fatal(err)
  278. }
  279. got, _, _, err := b.openInto(plain[:0], &rn, packet)
  280. if err != nil || !bytes.Equal(got, expected) {
  281. t.Fatal("in-place encryption corrupted packet", err)
  282. }
  283. }
  284. func TestSecureRekeyUnderTraffic(t *testing.T) {
  285. a, b := securePair(t)
  286. secureEstablish(t, a, b)
  287. var wg sync.WaitGroup
  288. started := make(chan struct{})
  289. wg.Add(1)
  290. go func() {
  291. defer wg.Done()
  292. var wire, plain [512]byte
  293. var tn, rn [24]byte
  294. close(started)
  295. for range 1000 {
  296. out, err := a.sealInto(wire[:0], &tn, 0, []byte("traffic during key rotation"))
  297. if err != nil {
  298. t.Error(err)
  299. return
  300. }
  301. if _, _, _, err = b.openInto(plain[:0], &rn, out); err != nil {
  302. t.Error(err)
  303. return
  304. }
  305. }
  306. }()
  307. <-started
  308. secureEstablish(t, a, b)
  309. wg.Wait()
  310. if a.handshakes.Load() != 2 || b.handshakes.Load() != 2 {
  311. t.Fatal("rotation not completed")
  312. }
  313. }
  314. func TestSecureCookieBindsSourceAndExpires(t *testing.T) {
  315. a, b := securePair(t)
  316. init, _ := a.initiation(1420, true)
  317. address := netip.MustParseAddrPort("192.0.2.10:51830")
  318. other := netip.MustParseAddrPort("192.0.2.11:51830")
  319. challenge, _, err := b.handleHandshake(init, 1420, address)
  320. if err != nil || challenge[3] != secureCookie {
  321. t.Fatal("missing source cookie", err)
  322. }
  323. request, _, err := a.handleHandshake(challenge, 1420)
  324. if err != nil {
  325. t.Fatal(err)
  326. }
  327. reply, _, err := b.handleHandshake(request, 1420, other)
  328. if err != nil || reply[3] != secureCookie || b.sessions.Load().pending != nil {
  329. t.Fatal("cookie accepted from another source", err)
  330. }
  331. expired := append([]byte(nil), request...)
  332. old := b.addressCookie(expired[:16], address, time.Now().Unix()/30-3)
  333. copy(expired[len(expired)-32:len(expired)-16], old[:])
  334. expired = a.finishHandshake(expired[:len(expired)-16])
  335. reply, _, err = b.handleHandshake(expired, 1420, address)
  336. if err != nil || reply[3] != secureCookie || b.sessions.Load().pending != nil {
  337. t.Fatal("expired cookie accepted", err)
  338. }
  339. if reply, _, err = b.handleHandshake(request, 1420, address); err != nil || reply[3] != secureResponse {
  340. t.Fatal("valid source cookie rejected", err)
  341. }
  342. }
  343. func TestSecureAllowedSourcePolicy(t *testing.T) {
  344. runner := TunnelRunner{allowed: []netip.Prefix{netip.MustParsePrefix("172.16.233.2/32"), netip.MustParsePrefix("2001:db8:42::/64")}}
  345. packet := make([]byte, 20)
  346. packet[0] = 0x45
  347. packet[3] = 20
  348. for _, tc := range []struct {
  349. source string
  350. want bool
  351. }{{"172.16.233.2", true}, {"172.16.233.1", false}, {"192.168.1.1", false}} {
  352. source := netip.MustParseAddr(tc.source).As4()
  353. copy(packet[12:16], source[:])
  354. if runner.allowedSource(packet) != tc.want {
  355. t.Fatalf("incorrect IPv4 source policy for %s", tc.source)
  356. }
  357. }
  358. v6 := make([]byte, 40)
  359. v6[0] = 0x60
  360. for _, tc := range []struct {
  361. source string
  362. want bool
  363. }{{"2001:db8:42::1", true}, {"2001:db8:43::1", false}, {"fe80::1423:58a:b322:ae3a", true}} {
  364. source := netip.MustParseAddr(tc.source).As16()
  365. copy(v6[8:24], source[:])
  366. if runner.allowedSource(v6) != tc.want {
  367. t.Fatalf("incorrect IPv6 source policy for %s", tc.source)
  368. }
  369. }
  370. }