func TestPeerLookup(t *testing.T) { bob.PeerLookup = func(k *[ed25519.PublicKeySize]byte) bool { return false } conn := testio.NewBufferConn() sk, _, err := bob.NewSession() if err != nil { t.Fatalf("%v", err) } conn.WritePeer(sk[:]) _, err = carol.Dial(conn) if err != nil { t.Fatalf("%v", err) } var csk [SessionKeySize]byte _, err = conn.ReadClient(csk[:]) if err != nil { t.Fatalf("%v", err) } _, ok := bob.VerifySessionKey(&csk) if ok { t.Fatal("carol should not be trusted by bob") } bob.PeerLookup = func(k *[ed25519.PublicKeySize]byte) bool { return true } conn = testio.NewBufferConn() sk, _, err = bob.NewSession() if err != nil { t.Fatalf("%v", err) } conn.WritePeer(sk[:]) _, err = carol.Dial(conn) if err != nil { t.Fatalf("%v", err) } util.Zero(csk[:]) _, err = conn.ReadClient(csk[:]) if err != nil { t.Fatalf("%v", err) } _, ok = bob.VerifySessionKey(&csk) if !ok { t.Fatal("carol should be trusted by bob") } bob.PeerLookup = nil }
func TestSessionSetup(t *testing.T) { pub, priv, err := GenerateKeyPair() if err != nil { t.Fatalf("%v", err) } conn := testio.NewBufferConn() conn.WritePeer(pub[:]) aliceSession, err = Dial(conn) if err != nil { t.Fatalf("%v", err) } var peer [64]byte _, err = conn.ReadClient(peer[:]) if err != nil { t.Fatalf("%v", err) } bobSession = &Session{ recvKey: new([32]byte), sendKey: new([32]byte), Channel: testio.NewBufCloser(nil), } bobSession.KeyExchange(priv, &peer, false) aliceSession.Channel = bobSession.Channel err = aliceSession.Send(testMessage) if err != nil { t.Fatalf("%v", err) } out, err := bobSession.Receive() if err != nil { t.Fatalf("%v", err) } if !bytes.Equal(out, testMessage) { t.Fatal("recovered message doesn't match original") } if err = aliceSession.Send(nil); err == nil { t.Fatal("empty message should trigger an error") } aliceSession.Close() bobSession.Close() }
func TestUntrusted(t *testing.T) { conn := testio.NewBufferConn() sk, _, err := bob.NewSession() if err != nil { t.Fatalf("%v", err) } conn.WritePeer(sk[:]) _, err = carol.Dial(conn) if err != nil { t.Fatalf("%v", err) } var csk [SessionKeySize]byte _, err = conn.ReadClient(csk[:]) if err != nil { t.Fatalf("%v", err) } _, ok := bob.VerifySessionKey(&csk) if ok { t.Fatal("carol should not be trusted by bob") } }
func TestSessionListen(t *testing.T) { pub, priv, err := GenerateKeyPair() if err != nil { t.Fatalf("%v", err) } conn := testio.NewBufferConn() conn.WritePeer(pub[:]) aliceSession, err = Listen(conn) if err != nil { t.Fatalf("%v", err) } var peer [64]byte _, err = conn.ReadClient(peer[:]) if err != nil { t.Fatalf("%v", err) } bobSession = &Session{ recvKey: new([32]byte), sendKey: new([32]byte), Channel: testio.NewBufCloser(nil), } bobSession.KeyExchange(priv, &peer, true) aliceSession.Channel = bobSession.Channel err = aliceSession.Send(testMessage) if err != nil { t.Fatalf("%v", err) } out, err := bobSession.Receive() if err != nil { t.Fatalf("%v", err) } // The NBA is always listening, on and off the court. oldMessage = out if !bytes.Equal(out, testMessage) { t.Fatal("recovered message doesn't match original") } for i := 0; i < 4; i++ { randMessage, err := util.RandBytes(128) if err != nil { t.Fatalf("%v", err) } err = aliceSession.Send(randMessage) if err != nil { t.Fatalf("%v", err) } out, err = bobSession.Receive() if err != nil { t.Fatal("%v", err) } if !bytes.Equal(out, randMessage) { t.Fatal("recovered message doesn't match original") } } // NBA injects an old message into the channel. Damn those hoops! bobSession.Channel.Write(oldMessage) _, err = bobSession.Receive() if err == nil { t.Fatal("NBA wins, you lose") } }
func TestDial(t *testing.T) { conn := testio.NewBufferConn() sk, bs, err := bob.NewSession() if err != nil { t.Fatalf("%v", err) } conn.WritePeer(sk[:]) as, err := alice.Dial(conn) if err != nil { t.Fatalf("%v", err) } var ask [SessionKeySize]byte _, err = conn.ReadClient(ask[:]) if err != nil { t.Fatalf("%v", err) } peer, ok := bob.VerifySessionKey(&ask) if !ok { t.Fatal("alice wasn't trusted by bob") } bs.Rekey(peer, false) buf := &bytes.Buffer{} as.Channel = buf bs.Channel = as.Channel err = as.Send(m) if err != nil { t.Fatalf("%v", err) } // TLA intercepted a message. first := buf.Bytes() rcv, err := bs.Receive() if err != nil { t.Fatalf("%v", err) } if !bytes.Equal(rcv, m) { t.Fatal("bob didn't get the right message") } for i := 0; i < 5; i++ { err = as.Send(m) if err != nil { t.Fatalf("%v", err) } rcv, err = bs.Receive() if err != nil { t.Fatalf("%v", err) } if !bytes.Equal(rcv, m) { t.Fatal("bob didn't get the right message") } } // TLA tries to replay message. as.Channel.Write(first) _, err = bs.Receive() if err == nil { t.Fatal("TLA wins.") } // \o/ bs.Close() as.Close() }
func testDial(t *testing.T, csk *[IdentityPrivateSize]byte, cpk *[IdentityPublicSize]byte, ssk *[IdentityPrivateSize]byte, spk *[IdentityPublicSize]byte, vok bool) { ch := testio.NewBufferConn() var pub [kexPubSize]byte var priv [kexPrvSize]byte if !generateKeypair(&priv, &pub) { t.Fatal("failed to generate keypair") } var kex [kexPubSize + SignatureSize]byte copy(kex[:], pub[:]) if !signKEX(&kex, ssk) { t.Fatal("failed to sign key exchange") } ch.WritePeer(kex[:]) alice, ok := Dial(ch, csk, spk) if !ok && vok { t.Fatal("failed to set up secure session") } else if ok && !vok { t.Fatal("secure session shouldn't have been set up") } if !vok { return } if !alice.Ready() { t.Fatal("alice is not ready") } if alice.RCtr() != 0 || alice.SCtr() != 0 { t.Fatal("alice's counters were not reset") } var peer [kexPubSize + SignatureSize]byte _, err := ch.ReadClient(peer[:]) if err != nil { t.Fatalf("%v", err) } ok = verifyKEX(&peer, cpk) if !ok && vok { t.Fatal("failed to verify key exchange") } else if ok && !vok { t.Fatal("key exchange verification should fail") } bob := &SChannel{} bob.reset() if !bob.doKEX(priv[:], peer[:kexPubSize], false) { t.Fatal("doKEX failed") } bob.ready = true buf := &bytes.Buffer{} if !bytes.Equal(alice.skey[:], bob.rkey[:]) { fmt.Printf("alice send key: %x\n", alice.skey) fmt.Printf(" bob recv key: %x\n", bob.rkey) t.Fatal("alice and bob have mismatched keys") } if !bytes.Equal(alice.rkey[:], bob.skey[:]) { fmt.Printf("alice recv key: %x\n", alice.rkey) fmt.Printf(" bob send key: %x\n", bob.skey) t.Fatal("alice and bob have mismatched keys") } bob.Channel = buf alice.Channel = buf if !alice.Send(message) { t.Fatal("alice failed to send a message") } // The dread TLA has captured our heroes' secure message! tlaCapture := buf.Bytes() m, ok := bob.Receive() if !ok { t.Fatal("bob couldn't receive the message") } else if m.Type != NormalMessage { t.Fatal("bob got an invalid message") } else if !bytes.Equal(m.Contents, message) { t.Fatal("bob didn't get the message alice sent") } for i := 0; i < 32; i++ { if !alice.Send(message) { t.Fatal("alice failed to send a message") } m, ok := bob.Receive() if !ok { t.Fatal("bob couldn't receive the message") } else if m.Type != NormalMessage { t.Fatal("bob got an invalid message") } else if !bytes.Equal(m.Contents, message) { t.Fatal("bob didn't get the message alice sent") } } buf.Write(tlaCapture) _, ok = bob.Receive() if ok { t.Fatal("the TLA won!") } // \o/ if !alice.Close() { t.Fatal("alice couldn't shutdown the channel") } if m, ok := bob.Receive(); !ok { t.Fatal("bob couldn't receive the message") } else if m.Type != ShutdownMessage { t.Fatal("bob expected a shutdown message") } bob.Zero() }