Beispiel #1
0
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
}
Beispiel #2
0
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()
}
Beispiel #3
0
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")
	}
}
Beispiel #4
0
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")
	}
}
Beispiel #5
0
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()
}
Beispiel #6
0
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()
}