1// Copyright 2015 Keybase, Inc. All rights reserved. Use of
2// this source code is governed by the included BSD license.
3
4package engine
5
6import (
7	"fmt"
8	"testing"
9
10	"github.com/keybase/client/go/libkb"
11	keybase1 "github.com/keybase/client/go/protocol/keybase1"
12	"github.com/stretchr/testify/require"
13)
14
15func withNewProvisionalLoginForFakeUser(m libkb.MetaContext, u *FakeUser) libkb.MetaContext {
16	m = m.WithNewProvisionalLoginContextForUserVersionAndUsername(u.UserVersion(), libkb.NewNormalizedUsername(u.Username))
17	return m
18}
19
20func tryPassphrase(tc libkb.TestContext, u *FakeUser, pp string) error {
21	m := NewMetaContextForTest(tc)
22	m = withNewProvisionalLoginForFakeUser(m, u)
23	_, err := libkb.VerifyPassphraseGetStreamInLoginContext(m, pp)
24	return err
25}
26
27func verifyPassphraseChange(tc libkb.TestContext, u *FakeUser, newPassphrase string) {
28	err := tryPassphrase(tc, u, newPassphrase)
29	require.NoError(tc.T, err, "verified new passphrase works")
30	err = tryPassphrase(tc, u, u.Passphrase)
31	require.Error(tc.T, err, "verified old passphrase fails")
32	if testing.Verbose() {
33		fmt.Printf("browser test -- username:  %s    password:  %s\n", u.Username, newPassphrase)
34	}
35}
36
37func assertLoadSecretKeys(tc libkb.TestContext, u *FakeUser, msg string) {
38	tc.G.Log.Debug("In assertLoadSecretKeys")
39
40	me, err := libkb.LoadMe(libkb.NewLoadUserArg(tc.G))
41	if err != nil {
42		tc.T.Fatalf("%s: %s", msg, err)
43	}
44	if me == nil {
45		tc.T.Fatalf("%s: nil LoadMe result", msg)
46	}
47	skarg := libkb.SecretKeyArg{
48		Me:      me,
49		KeyType: libkb.DeviceSigningKeyType,
50	}
51	parg := libkb.SecretKeyPromptArg{
52		Ska:      skarg,
53		SecretUI: u.NewSecretUI(),
54		Reason:   "testing sig",
55	}
56	m := NewMetaContextForTest(tc)
57	m = withNewProvisionalLoginForFakeUser(m, u)
58
59	tc.G.Log.Debug("doing a silent passphrase login for session token")
60	err = libkb.PassphraseLoginNoPrompt(m, u.Username, u.Passphrase)
61	require.NoError(tc.T, err)
62
63	tc.G.Log.Debug("Calling GetSecretKeyWithPrompt (for signing)")
64	sigKey, err := tc.G.Keyrings.GetSecretKeyWithPrompt(m, parg)
65	if err != nil {
66		tc.T.Fatalf("%s: %s", msg, err)
67	}
68	if sigKey == nil {
69		tc.T.Fatalf("%s: got nil signing key", msg)
70	}
71
72	parg.Ska.KeyType = libkb.DeviceEncryptionKeyType
73	tc.G.Log.Debug("Calling GetSecretKeyWithPrompt (for encryption)")
74	encKey, err := tc.G.Keyrings.GetSecretKeyWithPrompt(m, parg)
75	if err != nil {
76		tc.T.Fatalf("%s: %s", msg, err)
77	}
78	if encKey == nil {
79		tc.T.Fatalf("%s: got nil encryption key", msg)
80	}
81}
82
83func assertLoadPGPKeys(tc libkb.TestContext, u *FakeUser) {
84	me, err := libkb.LoadMe(libkb.NewLoadUserArg(tc.G))
85	if err != nil {
86		tc.T.Fatal(err)
87	}
88
89	ska := libkb.SecretKeyArg{
90		Me:      me,
91		KeyType: libkb.PGPKeyType,
92	}
93	parg := libkb.SecretKeyPromptArg{
94		Ska:      ska,
95		SecretUI: u.NewSecretUI(),
96		Reason:   "pgp test",
97	}
98	m := NewMetaContextForTest(tc)
99	key, err := tc.G.Keyrings.GetSecretKeyWithPrompt(m, parg)
100	if err != nil {
101		tc.T.Fatal(err)
102	}
103
104	var ok bool
105	_, ok = key.(*libkb.PGPKeyBundle)
106	if !ok {
107		tc.T.Errorf("key type: %T, expected libkb.PGPKeyBundle", key)
108	}
109}
110
111// Test changing the passphrase when user knows current
112// passphrase.
113func TestPassphraseChangeKnown(t *testing.T) {
114	tc := SetupEngineTest(t, "PassphraseChange")
115	defer tc.Cleanup()
116
117	u := CreateAndSignupFakeUser(tc, "login")
118	newPassphrase := "password1234"
119	arg := &keybase1.PassphraseChangeArg{
120		OldPassphrase: u.Passphrase,
121		Passphrase:    newPassphrase,
122	}
123
124	// using an empty secret ui to make sure existing pp doesn't come from ui prompt:
125	uis := libkb.UIs{
126		SecretUI: &libkb.TestSecretUI{},
127	}
128	eng := NewPassphraseChange(tc.G, arg)
129	m := NewMetaContextForTest(tc).WithUIs(uis)
130	if err := RunEngine2(m, eng); err != nil {
131		t.Fatal(err)
132	}
133
134	verifyPassphraseChange(tc, u, newPassphrase)
135
136	u.Passphrase = newPassphrase
137	assertLoadSecretKeys(tc, u, "passphrase change known")
138}
139
140// Test error when trying to change passphrase to shorter than 6
141// chars long.
142func TestPassphraseChangeShort(t *testing.T) {
143	tc := SetupEngineTest(t, "PassphraseChange")
144	defer tc.Cleanup()
145
146	u := CreateAndSignupFakeUser(tc, "login")
147	newPassphrase := "pass"
148	arg := &keybase1.PassphraseChangeArg{
149		OldPassphrase: u.Passphrase,
150		Passphrase:    newPassphrase,
151	}
152	uis := libkb.UIs{
153		SecretUI: &libkb.TestSecretUI{},
154	}
155	eng := NewPassphraseChange(tc.G, arg)
156	m := NewMetaContextForTest(tc).WithUIs(uis)
157	err := RunEngine2(m, eng)
158	if err == nil {
159		t.Fatal("expected error with new short passphrase")
160	}
161	if _, ok := err.(libkb.PassphraseError); !ok {
162		t.Fatalf("expected libkb.PassphraseError, got %T", err)
163	}
164}
165
166// Test changing the passphrase when user knows current
167// passphrase, prompt for it.
168func TestPassphraseChangeKnownPrompt(t *testing.T) {
169	tc := SetupEngineTest(t, "PassphraseChange")
170	defer tc.Cleanup()
171
172	u := CreateAndSignupFakeUser(tc, "login")
173
174	// clear the passphrase stream cache to force a prompt
175	// for the existing passphrase.
176	clearCaches(tc.G)
177
178	// Test changing passphrase 3 times; so that old passphrase
179	// cache is properly busted.
180	newPassphrase := "password1234"
181	numChanges := 3
182	for i := 0; i < numChanges; i++ {
183
184		arg := &keybase1.PassphraseChangeArg{
185			Passphrase: newPassphrase,
186		}
187		secui := u.NewSecretUI()
188		uis := libkb.UIs{
189			SecretUI: secui,
190		}
191		eng := NewPassphraseChange(tc.G, arg)
192		m := NewMetaContextForTest(tc).WithUIs(uis)
193		if err := RunEngine2(m, eng); err != nil {
194			t.Fatal(err)
195		}
196
197		// We only call this the last time through, since internally,
198		// verifyPassphraseChange calls ClearStreamCache(), which is
199		// the bug fix that we're actually trying to test by doing multiple
200		// passphrase changes.
201		if i == numChanges-1 {
202			verifyPassphraseChange(tc, u, newPassphrase)
203		}
204
205		if !secui.CalledGetPassphrase {
206			t.Errorf("get passphrase not called")
207		}
208
209		u.Passphrase = newPassphrase
210		assertLoadSecretKeys(tc, u, "passphrase change known prompt")
211		newPassphrase += "-xo"
212	}
213}
214
215// Test changing the passphrase when user knows current
216// passphrase, prompt for it.
217func TestPassphraseChangeKnownPromptRepeatOld(t *testing.T) {
218	tc := SetupEngineTest(t, "PassphraseChange")
219	defer tc.Cleanup()
220
221	u := CreateAndSignupFakeUser(tc, "login")
222	m := NewMetaContextForTest(tc)
223
224	// clear the passphrase stream cache to force a prompt
225	// for the existing passphrase.
226	m.ActiveDevice().ClearCaches()
227
228	// Test changing passphrase 3 times; so that old passphrase
229	// cache is properly busted.
230	newPassphrase := "password1234"
231	numChanges := 3
232	for i := 0; i < numChanges; i++ {
233
234		arg := &keybase1.PassphraseChangeArg{
235			Passphrase: newPassphrase,
236		}
237		secui := u.NewSecretUI()
238		uis := libkb.UIs{
239			SecretUI: secui,
240		}
241		eng := NewPassphraseChange(tc.G, arg)
242		m = m.WithUIs(uis)
243		if err := RunEngine2(m, eng); err != nil {
244			t.Fatal(err)
245		}
246
247		// We only call this the last time through, since internally,
248		// verifyPassphraseChange calls ClearStreamCache(), which is
249		// the bug fix that we're actually trying to test by doing multiple
250		// passphrase changes.
251		if i == numChanges-1 {
252			m := NewMetaContextForTest(tc)
253			_, err := libkb.VerifyPassphraseForLoggedInUser(m, newPassphrase)
254			if err != nil {
255				t.Fatal(err)
256			}
257		}
258
259		if !secui.CalledGetPassphrase {
260			t.Errorf("get passphrase not called")
261		}
262
263		u.Passphrase = newPassphrase
264		assertLoadSecretKeys(tc, u, "passphrase change known prompt")
265	}
266}
267
268// Test changing the passphrase after logging in via pubkey.
269func TestPassphraseChangeAfterPubkeyLogin(t *testing.T) {
270	tc := SetupEngineTest(t, "PassphraseChange")
271	defer tc.Cleanup()
272
273	u := CreateAndSignupFakeUser(tc, "login")
274
275	// this should do a pubkey login
276	Logout(tc)
277
278	secui := u.NewSecretUI()
279	if err := u.LoginWithSecretUI(secui, tc.G); err != nil {
280		t.Fatal(err)
281	}
282	if !secui.CalledGetPassphrase {
283		t.Errorf("get keybase passphrase not called")
284	}
285
286	newPassphrase := "password1234"
287	arg := &keybase1.PassphraseChangeArg{
288		Passphrase: newPassphrase,
289	}
290	uis := libkb.UIs{
291		SecretUI: secui,
292	}
293	eng := NewPassphraseChange(tc.G, arg)
294	m := NewMetaContextForTest(tc).WithUIs(uis)
295	if err := RunEngine2(m, eng); err != nil {
296		t.Fatal(err)
297	}
298
299	verifyPassphraseChange(tc, u, newPassphrase)
300
301	u.Passphrase = newPassphrase
302	assertLoadSecretKeys(tc, u, "passphrase change after pubkey login")
303}
304
305// Test changing the passphrase when previous pp stream available.
306func TestPassphraseChangeKnownNotSupplied(t *testing.T) {
307	tc := SetupEngineTest(t, "PassphraseChange")
308	defer tc.Cleanup()
309
310	u := CreateAndSignupFakeUser(tc, "login")
311	newPassphrase := "password1234"
312	arg := &keybase1.PassphraseChangeArg{
313		Passphrase: newPassphrase,
314	}
315	secui := &libkb.TestSecretUI{}
316	uis := libkb.UIs{
317		SecretUI: secui,
318	}
319	eng := NewPassphraseChange(tc.G, arg)
320	m := NewMetaContextForTest(tc).WithUIs(uis)
321	if err := RunEngine2(m, eng); err != nil {
322		t.Fatal(err)
323	}
324
325	verifyPassphraseChange(tc, u, newPassphrase)
326
327	if secui.CalledGetPassphrase {
328		t.Errorf("get kb passphrase called")
329	}
330
331	u.Passphrase = newPassphrase
332	assertLoadSecretKeys(tc, u, "passphrase change known, not supplied")
333}
334
335// Test changing the passphrase when user forgets current
336// passphrase.
337func TestPassphraseChangeUnknown(t *testing.T) {
338	tc := SetupEngineTest(t, "PassphraseChange")
339	defer tc.Cleanup()
340
341	u := CreateAndSignupFakeUser(tc, "login")
342
343	// this has a flaw:  the passphrase stream cache is available.
344	// it is being used to unlock the secret key to generate the
345	// change passphrase proof.
346	//
347
348	newPassphrase := "password1234"
349	arg := &keybase1.PassphraseChangeArg{
350		Passphrase: newPassphrase,
351		Force:      true,
352	}
353	uis := libkb.UIs{
354		SecretUI: &libkb.TestSecretUI{},
355	}
356	eng := NewPassphraseChange(tc.G, arg)
357	m := NewMetaContextForTest(tc).WithUIs(uis)
358	if err := RunEngine2(m, eng); err != nil {
359		t.Fatal(err)
360	}
361
362	verifyPassphraseChange(tc, u, newPassphrase)
363
364	u.Passphrase = newPassphrase
365	assertLoadSecretKeys(tc, u, "passphrase change unknown")
366}
367
368// Test changing the passphrase when user forgets current
369// passphrase and there's no passphrase stream cache.
370// No backup key available.
371func TestPassphraseChangeUnknownNoPSCache(t *testing.T) {
372	tc := SetupEngineTest(t, "PassphraseChange")
373	defer tc.Cleanup()
374
375	f := func(arg *SignupEngineRunArg) {
376		arg.SkipPaper = true
377	}
378
379	u, _, _ := CreateAndSignupFakeUserCustomArg(tc, "paper", f)
380
381	tc.SimulateServiceRestart()
382
383	newPassphrase := "password1234"
384	arg := &keybase1.PassphraseChangeArg{
385		Passphrase: newPassphrase,
386		Force:      true,
387	}
388	uis := libkb.UIs{
389		SecretUI: &libkb.TestSecretUI{},
390	}
391	eng := NewPassphraseChange(tc.G, arg)
392	m := NewMetaContextForTest(tc).WithUIs(uis)
393	err := RunEngine2(m, eng)
394	if err == nil {
395		t.Fatal("passphrase change should have failed")
396	}
397	if _, ok := err.(libkb.NoPaperKeysError); !ok {
398		t.Fatalf("unexpected error: %s (%T)", err, err)
399	}
400
401	assertLoadSecretKeys(tc, u, "passphrase change unknown, no ps cache")
402}
403
404// Test changing the passphrase when user forgets current
405// passphrase and there's no passphrase stream cache.
406// Backup key exists
407func TestPassphraseChangeUnknownBackupKey(t *testing.T) {
408	tc := SetupEngineTest(t, "PassphraseChange")
409	defer tc.Cleanup()
410
411	u := CreateAndSignupFakeUser(tc, "login")
412
413	uis := libkb.UIs{
414		LogUI:    tc.G.UI.GetLogUI(),
415		LoginUI:  &libkb.TestLoginUI{},
416		SecretUI: &libkb.TestSecretUI{},
417	}
418	beng := NewPaperKey(tc.G)
419	m := NewMetaContextForTest(tc).WithUIs(uis)
420	if err := RunEngine2(m, beng); err != nil {
421		t.Fatal(err)
422	}
423	backupPassphrase := beng.Passphrase()
424	m = m.WithSecretUI(&libkb.TestSecretUI{Passphrase: backupPassphrase})
425
426	m.ActiveDevice().ClearCaches()
427
428	newPassphrase := "password1234"
429	arg := &keybase1.PassphraseChangeArg{
430		Passphrase: newPassphrase,
431		Force:      true,
432	}
433	eng := NewPassphraseChange(tc.G, arg)
434	if err := RunEngine2(m, eng); err != nil {
435		t.Fatal(err)
436	}
437
438	verifyPassphraseChange(tc, u, newPassphrase)
439
440	u.Passphrase = newPassphrase
441	assertLoadSecretKeys(tc, u, "passphrase change unknown, backup key")
442}
443
444// Test changing the passphrase when user forgets current
445// passphrase and is logged out, but has a backup key.
446func TestPassphraseChangeLoggedOutBackupKey(t *testing.T) {
447	tc := SetupEngineTest(t, "PassphraseChange")
448	defer tc.Cleanup()
449
450	u := CreateAndSignupFakeUser(tc, "login")
451
452	assertLoadSecretKeys(tc, u, "logged out w/ backup key, before passphrase change")
453
454	uis := libkb.UIs{
455		LogUI:    tc.G.UI.GetLogUI(),
456		LoginUI:  &libkb.TestLoginUI{},
457		SecretUI: &libkb.TestSecretUI{},
458	}
459	beng := NewPaperKey(tc.G)
460	m := NewMetaContextForTest(tc).WithUIs(uis)
461	if err := RunEngine2(m, beng); err != nil {
462		t.Fatal(err)
463	}
464	backupPassphrase := beng.Passphrase()
465	m = m.WithSecretUI(&libkb.TestSecretUI{Passphrase: backupPassphrase})
466
467	Logout(tc)
468
469	newPassphrase := "password1234"
470	arg := &keybase1.PassphraseChangeArg{
471		Passphrase: newPassphrase,
472		Force:      true,
473	}
474	eng := NewPassphraseChange(tc.G, arg)
475	if err := RunEngine2(m, eng); err != nil {
476		t.Fatal(err)
477	}
478
479	verifyPassphraseChange(tc, u, newPassphrase)
480
481	u.Passphrase = newPassphrase
482	assertLoadSecretKeys(tc, u, "logged out w/ backup key, after passphrase change")
483}
484
485// Test changing the passphrase when user forgets current passphrase
486// and is logged out, but has a backup key (generated by a secret from
487// the secret store).
488func TestPassphraseChangeLoggedOutBackupKeySecretStore(t *testing.T) {
489
490	tc := SetupEngineTest(t, "PassphraseChange")
491	defer tc.Cleanup()
492
493	u := NewFakeUserOrBust(tc.T, "login")
494	signupArg := MakeTestSignupEngineRunArg(u)
495	signupArg.StoreSecret = true
496	_ = SignupFakeUserWithArg(tc, u, signupArg)
497
498	// This needs to happen *before* resetting the login state, as
499	// this call will cause the login state to be reloaded.
500	assertLoadSecretKeys(tc, u, "logged out w/ backup key, before passphrase change")
501
502	tc.SimulateServiceRestart()
503
504	secretUI := libkb.TestSecretUI{}
505	uis := libkb.UIs{
506		LogUI:    tc.G.UI.GetLogUI(),
507		LoginUI:  &libkb.TestLoginUI{},
508		SecretUI: &secretUI,
509	}
510	beng := NewPaperKey(tc.G)
511	m := NewMetaContextForTest(tc).WithUIs(uis)
512	if err := RunEngine2(m, beng); err != nil {
513		t.Fatal(err)
514	}
515
516	if secretUI.CalledGetPassphrase {
517		t.Fatal("GetPassphrase() unexpectedly called")
518	}
519
520	backupPassphrase := beng.Passphrase()
521	m = m.WithSecretUI(&libkb.TestSecretUI{Passphrase: backupPassphrase})
522
523	Logout(tc)
524
525	newPassphrase := "password1234"
526	arg := &keybase1.PassphraseChangeArg{
527		Passphrase: newPassphrase,
528		Force:      true,
529	}
530	eng := NewPassphraseChange(tc.G, arg)
531	if err := RunEngine2(m, eng); err != nil {
532		t.Fatal(err)
533	}
534
535	verifyPassphraseChange(tc, u, newPassphrase)
536
537	u.Passphrase = newPassphrase
538	assertLoadSecretKeys(tc, u, "logged out w/ backup key, after passphrase change")
539}
540
541// Test using an lksec-encrypted pgp private key after changing the
542// passphrase.
543func TestPassphraseChangePGPUsage(t *testing.T) {
544	tc := SetupEngineTest(t, "PassphraseChange")
545	defer tc.Cleanup()
546
547	u := createFakeUserWithPGPSibkey(tc)
548
549	// clear the passphrase stream cache to force a prompt
550	// for the existing passphrase.
551	clearCaches(tc.G)
552
553	newPassphrase := "password1234"
554	arg := &keybase1.PassphraseChangeArg{
555		Passphrase: newPassphrase,
556	}
557	secui := u.NewSecretUI()
558	uis := libkb.UIs{
559		SecretUI: secui,
560	}
561	eng := NewPassphraseChange(tc.G, arg)
562	m := NewMetaContextForTest(tc).WithUIs(uis)
563	if err := RunEngine2(m, eng); err != nil {
564		t.Fatal(err)
565	}
566
567	verifyPassphraseChange(tc, u, newPassphrase)
568
569	if !secui.CalledGetPassphrase {
570		t.Errorf("get kb passphrase not called")
571	}
572
573	u.Passphrase = newPassphrase
574	assertLoadSecretKeys(tc, u, "passphrase change pgp")
575	assertLoadPGPKeys(tc, u)
576}
577
578// Test using a 3sec-encrypted pgp private key after changing the
579// passphrase.
580func TestPassphraseChangePGP3Sec(t *testing.T) {
581	tc := SetupEngineTest(t, "PassphraseChange")
582	defer tc.Cleanup()
583
584	u := createFakeUserWithPGPSibkeyPushed(tc)
585
586	// clear the passphrase stream cache to force a prompt
587	// for the existing passphrase.
588	clearCaches(tc.G)
589
590	newPassphrase := "password1234"
591	arg := &keybase1.PassphraseChangeArg{
592		Passphrase: newPassphrase,
593	}
594	secui := u.NewSecretUI()
595	uis := libkb.UIs{
596		SecretUI: secui,
597	}
598	eng := NewPassphraseChange(tc.G, arg)
599	m := NewMetaContextForTest(tc).WithUIs(uis)
600	if err := RunEngine2(m, eng); err != nil {
601		t.Fatal(err)
602	}
603
604	verifyPassphraseChange(tc, u, newPassphrase)
605
606	if !secui.CalledGetPassphrase {
607		t.Errorf("get kb passphrase not called")
608	}
609
610	u.Passphrase = newPassphrase
611	assertLoadSecretKeys(tc, u, "passphrase change pgp")
612	assertLoadPGPKeys(tc, u)
613}
614
615// Test changing the passphrase when user forgets current
616// passphrase and is logged out, but has a backup key.
617// Also, this user has a 3sec-encrypted private pgp key
618// that will be unusable after changing passphrase.
619func TestPassphraseChangeLoggedOutBackupKeyPlusPGP(t *testing.T) {
620	tc := SetupEngineTest(t, "PassphraseChange")
621	defer tc.Cleanup()
622
623	u := createFakeUserWithPGPSibkeyPushed(tc)
624
625	assertLoadSecretKeys(tc, u, "logged out w/ backup key, before passphrase change")
626
627	uis := libkb.UIs{
628		LogUI:    tc.G.UI.GetLogUI(),
629		LoginUI:  &libkb.TestLoginUI{},
630		SecretUI: &libkb.TestSecretUI{},
631	}
632	beng := NewPaperKey(tc.G)
633	m := NewMetaContextForTest(tc).WithUIs(uis)
634	if err := RunEngine2(m, beng); err != nil {
635		t.Fatal(err)
636	}
637	backupPassphrase := beng.Passphrase()
638	m = m.WithSecretUI(&libkb.TestSecretUI{Passphrase: backupPassphrase})
639	Logout(tc)
640
641	newPassphrase := "password1234"
642	arg := &keybase1.PassphraseChangeArg{
643		Passphrase: newPassphrase,
644		Force:      true,
645	}
646	eng := NewPassphraseChange(tc.G, arg)
647	if err := RunEngine2(m, eng); err != nil {
648		t.Fatal(err)
649	}
650
651	verifyPassphraseChange(tc, u, newPassphrase)
652
653	u.Passphrase = newPassphrase
654	assertLoadSecretKeys(tc, u, "logged out w/ backup key, after passphrase change")
655}
656
657// Test changing the passphrase when user forgets current passphrase
658// and is logged out, but has a backup key (generated by a secret from
659// the secret store).  And test using an lksec pgp key after the change.
660func TestPassphraseChangeLoggedOutBackupKeySecretStorePGP(t *testing.T) {
661
662	tc := SetupEngineTest(t, "PassphraseChange")
663	defer tc.Cleanup()
664
665	u := NewFakeUserOrBust(tc.T, "login")
666	signupArg := MakeTestSignupEngineRunArg(u)
667	signupArg.StoreSecret = true
668	_ = SignupFakeUserWithArg(tc, u, signupArg)
669
670	// add a pgp sibkey, pushed to server and stored locally (lksec)
671	arg := PGPKeyImportEngineArg{
672		Gen: &libkb.PGPGenArg{
673			PrimaryBits: 768,
674			SubkeyBits:  768,
675		},
676		PushSecret: true,
677	}
678	err := arg.Gen.MakeAllIds(tc.G)
679	require.NoError(t, err)
680	uis := libkb.UIs{
681		LogUI:    tc.G.UI.GetLogUI(),
682		SecretUI: u.NewSecretUI(),
683	}
684	eng := NewPGPKeyImportEngine(tc.G, arg)
685	m := NewMetaContextForTest(tc).WithUIs(uis)
686	err = RunEngine2(m, eng)
687	if err != nil {
688		tc.T.Fatal(err)
689	}
690
691	// This needs to happen *before* resetting the login state, as
692	// this call will cause the login state to be reloaded.
693	assertLoadSecretKeys(tc, u, "logged out w/ backup key, before passphrase change")
694
695	tc.SimulateServiceRestart()
696
697	secretUI := libkb.TestSecretUI{}
698	uis = libkb.UIs{
699		LogUI:    tc.G.UI.GetLogUI(),
700		LoginUI:  &libkb.TestLoginUI{},
701		SecretUI: &secretUI,
702	}
703	beng := NewPaperKey(tc.G)
704	m = NewMetaContextForTest(tc).WithUIs(uis)
705	if err := RunEngine2(m, beng); err != nil {
706		t.Fatal(err)
707	}
708
709	if secretUI.CalledGetPassphrase {
710		t.Fatal("GetPassphrase() unexpectedly called")
711	}
712
713	backupPassphrase := beng.Passphrase()
714	m = m.WithSecretUI(&libkb.TestSecretUI{Passphrase: backupPassphrase})
715
716	Logout(tc)
717
718	newPassphrase := "password1234"
719	pcarg := &keybase1.PassphraseChangeArg{
720		Passphrase: newPassphrase,
721		Force:      true,
722	}
723	pceng := NewPassphraseChange(tc.G, pcarg)
724	if err := RunEngine2(m, pceng); err != nil {
725		t.Fatal(err)
726	}
727
728	verifyPassphraseChange(tc, u, newPassphrase)
729
730	u.Passphrase = newPassphrase
731	assertLoadSecretKeys(tc, u, "logged out w/ backup key, after passphrase change")
732	assertLoadPGPKeys(tc, u)
733}
734
735// test pp change when user has multiple 3sec encrypted pgp keys.
736func TestPassphraseChangePGP3SecMultiple(t *testing.T) {
737	tc := SetupEngineTest(t, "PassphraseChange")
738	defer tc.Cleanup()
739
740	u := createFakeUserWithPGPSibkeyPushed(tc)
741
742	// create/push another pgp key
743	parg := PGPKeyImportEngineArg{
744		Gen: &libkb.PGPGenArg{
745			PrimaryBits: 768,
746			SubkeyBits:  768,
747		},
748		PushSecret: true,
749		NoSave:     true,
750		AllowMulti: true,
751	}
752	err := parg.Gen.MakeAllIds(tc.G)
753	require.NoError(t, err)
754	uis := libkb.UIs{
755		LogUI:    tc.G.UI.GetLogUI(),
756		SecretUI: u.NewSecretUI(),
757	}
758	peng := NewPGPKeyImportEngine(tc.G, parg)
759	m := NewMetaContextForTest(tc).WithUIs(uis)
760	err = RunEngine2(m, peng)
761	if err != nil {
762		t.Fatal(err)
763	}
764
765	// clear the passphrase stream cache to force a prompt
766	// for the existing passphrase.
767	clearCaches(tc.G)
768
769	newPassphrase := "password1234"
770	arg := &keybase1.PassphraseChangeArg{
771		Passphrase: newPassphrase,
772	}
773	secui := u.NewSecretUI()
774	uis = libkb.UIs{
775		SecretUI: secui,
776	}
777	eng := NewPassphraseChange(tc.G, arg)
778	m = NewMetaContextForTest(tc).WithUIs(uis)
779	if err := RunEngine2(m, eng); err != nil {
780		t.Fatal(err)
781	}
782
783	verifyPassphraseChange(tc, u, newPassphrase)
784
785	if !secui.CalledGetPassphrase {
786		t.Errorf("get kb passphrase not called")
787	}
788
789	u.Passphrase = newPassphrase
790	assertLoadSecretKeys(tc, u, "passphrase change pgp")
791	assertLoadPGPKeys(tc, u)
792
793	me, err := libkb.LoadMe(libkb.NewLoadUserForceArg(tc.G))
794	if err != nil {
795		t.Fatal(err)
796	}
797	syncKeys, err := me.AllSyncedSecretKeys(m)
798	if err != nil {
799		t.Fatal(err)
800	}
801	if len(syncKeys) != 2 {
802		t.Errorf("num pgp sync keys: %d, expected 2", len(syncKeys))
803	}
804	for _, key := range syncKeys {
805		parg := libkb.SecretKeyPromptArg{
806			SecretUI: u.NewSecretUI(),
807		}
808		unlocked, err := key.PromptAndUnlock(m, parg, nil, me)
809		if err != nil {
810			t.Fatal(err)
811		}
812		if unlocked == nil {
813			t.Fatal("failed to unlock key")
814		}
815	}
816}
817
818// Make sure passphrase generations are stored properly alongside encrypted keys.
819// We'll create a user, check the ppgens of the initial pair of keys, change the
820// passphrase, create a new key, and then they the ppgen of that new one (which
821// should be higher).
822func TestPassphraseGenerationStored(t *testing.T) {
823	tc := SetupEngineTest(t, "PassphraseChange")
824	defer tc.Cleanup()
825
826	u := CreateAndSignupFakeUser(tc, "login")
827	mctx := tc.MetaContext()
828
829	// All of the keys initially created with the user should be stored as
830	// passphrase generation 1.
831	skbKeyringFile, err := libkb.LoadSKBKeyring(mctx, u.NormalizedUsername())
832	if err != nil {
833		t.Fatal(err)
834	}
835	initialGenerationOneCount := 0
836	for _, block := range skbKeyringFile.Blocks {
837		if block.Priv.PassphraseGeneration != 1 {
838			t.Fatalf("Expected all encrypted keys to be ppgen 1. Found %d.",
839				block.Priv.PassphraseGeneration)
840		}
841		initialGenerationOneCount++
842	}
843
844	//
845	// Do a passphrase change.
846	//
847	newPassphrase := "password1234"
848	arg := &keybase1.PassphraseChangeArg{
849		OldPassphrase: u.Passphrase,
850		Passphrase:    newPassphrase,
851	}
852	uis := libkb.UIs{
853		LogUI:    tc.G.UI.GetLogUI(),
854		SecretUI: u.NewSecretUI(),
855	}
856	eng := NewPassphraseChange(tc.G, arg)
857	m := NewMetaContextForTest(tc).WithUIs(uis)
858	if err := RunEngine2(m, eng); err != nil {
859		t.Fatal(err)
860	}
861	u.Passphrase = newPassphrase
862
863	//
864	// Now, generate a new key. This one should be stored with ppgen 2.
865	//
866	pgpArg := PGPKeyImportEngineArg{
867		Gen: &libkb.PGPGenArg{
868			PrimaryBits: 768,
869			SubkeyBits:  768,
870		},
871	}
872	err = pgpArg.Gen.MakeAllIds(tc.G)
873	require.NoError(t, err)
874	pgpEng := NewPGPKeyImportEngine(tc.G, pgpArg)
875	uis = libkb.UIs{
876		LogUI:    tc.G.UI.GetLogUI(),
877		SecretUI: u.NewSecretUI(),
878	}
879	m = NewMetaContextForTest(tc).WithUIs(uis)
880	err = RunEngine2(m, pgpEng)
881	if err != nil {
882		t.Fatal(err)
883	}
884
885	//
886	// Finally, check that the new key (and only the new key) is marked as ppgen 2.
887	//
888	finalSKBKeyringFile, err := libkb.LoadSKBKeyring(mctx, u.NormalizedUsername())
889	if err != nil {
890		t.Fatal(err)
891	}
892	finalGenOneCount := 0
893	finalGenTwoCount := 0
894	for _, block := range finalSKBKeyringFile.Blocks {
895		if block.Priv.PassphraseGeneration == 1 {
896			finalGenOneCount++
897		} else if block.Priv.PassphraseGeneration == 2 {
898			finalGenTwoCount++
899		} else {
900			t.Fatalf("Expected all encrypted keys to be ppgen 1 or 2. Found %d.",
901				block.Priv.PassphraseGeneration)
902		}
903	}
904	if finalGenOneCount != initialGenerationOneCount {
905		t.Fatalf("Expected initial count of ppgen 1 keys (%d) to equal final count (%d).",
906			initialGenerationOneCount, finalGenOneCount)
907	}
908	if finalGenTwoCount != 1 {
909		t.Fatalf("Expected one key in ppgen 2. Found %d keys.", finalGenTwoCount)
910	}
911}
912