// Run starts the engine.
func (k *KexProvisioner) Run(ctx *Context) error {
	k.engctx = ctx

	var err error
	uarg := libkb.NewLoadUserPubOptionalArg(k.G())
	uarg.LoginContext = ctx.LoginContext
	k.user, err = libkb.LoadMe(uarg)
	if err != nil {
		return err
	}

	dp := k.G().Env.GetDeviceID()
	if dp.IsNil() {
		// Prereqs w/ Device: true should catch this earlier, but just in case:
		return libkb.DeviceRequiredError{}
	}
	k.deviceID = dp
	k.G().Log.Debug("device id: %s", k.deviceID)

	if k.user.GetComputedKeyFamily() == nil {
		return libkb.KeyFamilyError{Msg: "nil ckf"}
	}

	k.deviceSibkey, err = k.user.GetComputedKeyFamily().GetSibkeyForDevice(k.deviceID)
	if err != nil {
		k.G().Log.Warning("KexProvisioner.Run: error getting device sibkey: %s", err)
		return err
	}

	token, csrf := k.sessionArgs(ctx)

	k.sec, err = kex.SecretFromPhrase(k.user.GetName(), k.secretPhrase)
	if err != nil {
		return err
	}
	k.serverMu.Lock()
	k.server = kex.NewSender(kex.DirectionXtoY, k.sec.Secret(), token, csrf, k.G())
	k.serverMu.Unlock()

	arg := libkb.SecretKeyArg{
		Me:      k.user,
		KeyType: libkb.DeviceSigningKeyType,
	}
	k.sigKey, err = k.G().Keyrings.GetSecretKeyWithPrompt(ctx.LoginContext, arg, ctx.SecretUI, "new device install")
	if err != nil {
		k.G().Log.Warning("KexProvisioner.Run: GetSecretKey error: %s", err)
		return err
	}

	k.G().Log.Debug("KexProvisioner: starting receive loop")
	var nilDeviceID keybase1.DeviceID
	m := kex.NewMeta(k.user.GetUID(), k.sec.StrongID(), nilDeviceID, k.deviceID, kex.DirectionYtoX)
	err = k.loopReceives(ctx, m, k.sec)
	if err != nil {
		k.G().Log.Warning("Error in KEX receive: %s", err)
	}
	return err
}
示例#2
0
// 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")
	}
}
示例#3
0
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)
	}
}
示例#4
0
// 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
}