// TestBasicMessage verifies that a message can be sent and // received. func TestBasicMessage(t *testing.T) { tc := SetupEngineTest(t, "kex") defer tc.Cleanup() fu := CreateAndSignupFakeUser(tc, "login") sec, err := kex.NewSecret(fu.Username) if err != nil { t.Fatal(err) } var tok, csrf string err = tc.G.LoginState().LocalSession(func(s *libkb.Session) { tok, csrf = s.APIArgs() }, "TestBasicMessage") if err != nil { t.Fatal(err) } s := kex.NewSender(kex.DirectionYtoX, sec.Secret(), tok, csrf, tc.G) r := kex.NewReceiver(kex.DirectionYtoX, sec, tok, csrf, tc.G) ctx := testKexMeta(t, fu.Username, sec) if err := s.StartKexSession(ctx, ctx.StrongID); err != nil { t.Fatal(err) } rctx := testKexMeta(t, fu.Username, sec) rctx.Swap() n, err := r.Receive(rctx) if err != nil { t.Fatal(err) } if n != 1 { t.Errorf("receive count: %d, expected 1", n) } select { case msg := <-r.Msgs: if msg.Name() != kex.StartKexMsg { t.Errorf("msg: %s, expected %s", msg.Name(), kex.StartKexMsg) } default: t.Fatal("no msg in r.Msgs") } }
func TestBadMACMessage(t *testing.T) { tc := SetupEngineTest(t, "kex") defer tc.Cleanup() fu := CreateAndSignupFakeUser(tc, "login") sec, err := kex.NewSecret(fu.Username) if err != nil { t.Fatal(err) } var tok, csrf string err = tc.G.LoginState().LocalSession(func(s *libkb.Session) { tok, csrf = s.APIArgs() }, "TestBadMACMessage") if err != nil { t.Fatal(err) } s := kex.NewSender(kex.DirectionYtoX, sec.Secret(), tok, csrf, tc.G) r := kex.NewReceiver(kex.DirectionYtoX, sec, tok, csrf, tc.G) ctx := testKexMeta(t, fu.Username, sec) if err := s.CorruptStartKexSession(ctx, ctx.StrongID); err != nil { t.Fatal(err) } rctx := testKexMeta(t, fu.Username, sec) rctx.Swap() n, err := r.Receive(rctx) if err != nil { t.Fatal(err) } if n != 0 { t.Errorf("receive count: %d, expected 0", n) } }
// Run starts the engine. func (k *KexNewDevice) Run(ctx *Context) error { k.G().Log.Debug("KexNewDevice: run starting") defer k.G().Log.Debug("KexNewDevice: run finished") k.user = k.args.User if k.args.DevDesc == "" { return errors.New("Empty device description passed to kex") } // register a new device ndarg := &DeviceRegisterArgs{ Me: k.user, Name: k.args.DevDesc, Lks: k.lks, } devreg := NewDeviceRegister(ndarg, k.G()) if err := RunEngine(devreg, ctx); err != nil { return err } k.deviceID = devreg.DeviceID() token, csrf := k.sessionArgs(ctx) // make random secret S, session id I sec, err := kex.NewSecret(k.user.GetName()) if err != nil { return err } k.secret = sec k.serverMu.Lock() k.server = kex.NewSender(kex.DirectionYtoX, k.secret.Secret(), token, csrf, k.G()) k.serverMu.Unlock() // create the kex meta data m := kex.NewMeta(k.args.User.GetUID(), k.secret.StrongID(), k.deviceID, k.args.Dst, kex.DirectionXtoY) // start message receive loop k.poll(ctx, m, sec) // tell user the command to enter on existing device (X) // note: this has to happen before StartKexSession call for tests to work. k.G().Log.Debug("KexNewDevice: displaying sibkey command") darg := keybase1.DisplaySecretWordsArg{ DeviceNameToAdd: k.args.DevDesc, DeviceNameExisting: k.args.DstName, Secret: sec.Phrase(), } if err := ctx.LocksmithUI.DisplaySecretWords(context.TODO(), darg); err != nil { return err } // start the kex session with X k.G().Log.Debug("KexNewDevice: sending StartKexSession to X") k.kexStatus(ctx, "sending StartKexSession to X", keybase1.KexStatusCode_START_SEND) if err := k.server.StartKexSession(m, k.secret.StrongID()); err != nil { return err } // wait for Hello() from X k.kexStatus(ctx, "waiting for Hello from X", keybase1.KexStatusCode_HELLO_WAIT) if err := k.next(ctx, kex.HelloMsg, kex.HelloTimeout, k.handleHello); err != nil { return err } k.kexStatus(ctx, "received Hello from X", keybase1.KexStatusCode_HELLO_RECEIVED) dkargs := &DeviceKeygenArgs{ Me: k.user, DeviceID: k.deviceID, DeviceName: k.args.DevDesc, DeviceType: libkb.DeviceTypeDesktop, Lks: k.lks, } dkeng := NewDeviceKeygen(dkargs, k.G()) if err := RunEngine(dkeng, ctx); err != nil { return err } signerPub, err := dkeng.SigningKeyPublic() if err != nil { return err } // get reverse signature of X's device key rsig, err := k.revSig(dkeng.SigningKey()) if err != nil { return err } // send PleaseSign message to X m.Sender = k.deviceID m.Receiver = k.args.Dst k.G().Log.Debug("KexNewDevice: sending PleaseSign to X") k.kexStatus(ctx, "sending PleaseSign to X", keybase1.KexStatusCode_PLEASE_SIGN_SEND) if err := k.server.PleaseSign(m, signerPub, rsig, k.args.DevType, k.args.DevDesc); err != nil { return err } // wait for Done() from X k.kexStatus(ctx, "waiting for Done from X", keybase1.KexStatusCode_DONE_WAIT) if err := k.next(ctx, kex.DoneMsg, kex.IntraTimeout, k.handleDone); err != nil { return err } k.kexStatus(ctx, "received Done from X", keybase1.KexStatusCode_DONE_RECEIVED) // push the dh key as a subkey to the server k.G().Log.Debug("KexNewDevice: pushing subkey") pargs := &DeviceKeygenPushArgs{ SkipSignerPush: true, Signer: dkeng.SigningKey(), EldestKID: k.user.GetEldestKID(), User: k.user, } if err := dkeng.Push(ctx, pargs); err != nil { k.G().Log.Debug("error running dkeng.Push(): %s", err) k.G().Log.Debug("push args: %+v", pargs) return err } k.wg.Wait() k.kexStatus(ctx, "kexfwd complete on new device Y", keybase1.KexStatusCode_END) return nil }