| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- package aerotun
- import (
- "bytes"
- "encoding/binary"
- "errors"
- "testing"
- )
- const testPSK = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
- func testProtocol(t *testing.T) *protocolState {
- t.Helper()
- p, err := newProtocol(testPSK)
- if err != nil {
- t.Fatal(err)
- }
- return p
- }
- func testSeal(t *testing.T, p *protocolState, flags byte, b []byte, target sessionID) []byte {
- t.Helper()
- if flags != 0 && flags != FlagCompressedLZ4 && b == nil {
- b = []byte{5, 140}
- } // 1420-byte MTU advertisement
- out, err := p.seal(flags, b, target)
- if err != nil {
- t.Fatal(err)
- }
- return out
- }
- func establish(t *testing.T, a, b *protocolState) {
- t.Helper()
- hello := testSeal(t, a, flagHello, nil, zeroSession)
- _, _, sender, _, err := b.open(hello)
- if err != nil {
- t.Fatal(err)
- }
- ack := testSeal(t, b, flagAck, nil, sender)
- _, _, sender, _, err = a.open(ack)
- if err != nil {
- t.Fatal(err)
- }
- confirm := testSeal(t, a, flagConfirm, nil, sender)
- if _, _, _, _, err = b.open(confirm); err != nil {
- t.Fatal(err)
- }
- }
- func TestProtocolAuthenticationReplayAndRestart(t *testing.T) {
- a, b := testProtocol(t), testProtocol(t)
- establish(t, a, b)
- forward := testSeal(t, a, 0, []byte("forward"), zeroSession)
- reverse := testSeal(t, b, 0, []byte("reverse"), zeroSession)
- if bytes.Equal(forward[4:44], reverse[4:44]) {
- t.Fatal("directions reuse nonce/key context")
- }
- bad := append([]byte(nil), forward...)
- binary.BigEndian.PutUint64(bad[36:44], 1<<60)
- if _, _, _, _, err := b.open(bad); err == nil {
- t.Fatal("tampered counter authenticated")
- }
- got, _, _, _, err := b.open(forward)
- if err != nil || string(got) != "forward" {
- t.Fatalf("valid data rejected after forgery: %q %v", got, err)
- }
- if _, _, _, _, err = b.open(forward); !errors.Is(err, errReplay) {
- t.Fatalf("duplicate accepted: %v", err)
- }
- if _, _, _, _, err = a.open(forward); err == nil {
- t.Fatal("reflected data accepted")
- }
- if got, _, _, _, err = a.open(reverse); err != nil || string(got) != "reverse" {
- t.Fatal(err)
- }
- oldAck := testSeal(t, a, flagAck, nil, b.local)
- // Reboot sender: old packets and old ACKs cannot reactivate a retired session.
- a2 := testProtocol(t)
- establish(t, a2, b)
- if _, _, _, _, err = b.open(oldAck); err == nil {
- t.Fatal("retired peer session accepted")
- }
- if _, _, _, _, err = b.open(forward); err == nil {
- t.Fatal("old data accepted after sender restart")
- }
- fresh := testSeal(t, a2, 0, []byte("after restart"), zeroSession)
- if _, _, _, _, err = b.open(fresh); err != nil {
- t.Fatal(err)
- }
- // Reboot receiver: even authentic recordings target its obsolete boot ID.
- b2 := testProtocol(t)
- if _, _, _, _, err = b2.open(fresh); err == nil {
- t.Fatal("old data accepted after receiver restart")
- }
- establish(t, a2, b2)
- if _, _, _, _, err = b2.open(testSeal(t, a2, 0, []byte("new receiver"), zeroSession)); err != nil {
- t.Fatal(err)
- }
- }
- func TestHelloDoesNotReplaceSession(t *testing.T) {
- a, b := testProtocol(t), testProtocol(t)
- establish(t, a, b)
- stranger := testProtocol(t)
- _, _, _, _, err := b.open(testSeal(t, stranger, flagHello, nil, zeroSession))
- if err != nil {
- t.Fatal(err)
- }
- if b.remote != a.local {
- t.Fatal("HELLO replaced established session")
- }
- wrong, err := newProtocol("a completely different shared secret")
- if err != nil {
- t.Fatal(err)
- }
- if _, _, _, _, err = b.open(testSeal(t, wrong, flagHello, nil, zeroSession)); err == nil {
- t.Fatal("wrong PSK accepted")
- }
- }
- func TestReplayWindow(t *testing.T) {
- var w replayWindow
- for _, n := range []uint64{1, 3, 2, 66, 65} {
- if !w.accept(n) {
- t.Fatalf("valid counter %d rejected", n)
- }
- }
- for _, n := range []uint64{0, 1, 2, 3, 65, 66} {
- if w.accept(n) {
- t.Fatalf("invalid counter %d accepted", n)
- }
- }
- }
- func TestHandshakeConfirmationRetry(t *testing.T) {
- a, b := testProtocol(t), testProtocol(t)
- hello := testSeal(t, a, flagHello, nil, zeroSession)
- _, _, sender, _, err := b.open(hello)
- if err != nil {
- t.Fatal(err)
- }
- ack := testSeal(t, b, flagAck, nil, sender)
- _, _, _, _, err = a.open(ack)
- if err != nil {
- t.Fatal(err)
- }
- // First confirmation is lost. Repeated HELLO -> ACK -> CONFIRM still works.
- establish(t, a, b)
- if _, _, _, _, err = b.open(testSeal(t, a, 0, []byte("data"), zeroSession)); err != nil {
- t.Fatal(err)
- }
- }
|