1package libkb
2
3import (
4	"errors"
5	"fmt"
6	"sync"
7
8	"github.com/keybase/client/go/protocol/keybase1"
9	context "golang.org/x/net/context"
10)
11
12type ActiveDevice struct {
13	uv            keybase1.UserVersion
14	deviceID      keybase1.DeviceID
15	deviceName    string
16	deviceCtime   keybase1.Time
17	signingKey    GenericKey   // cached secret signing key
18	encryptionKey GenericKey   // cached secret encryption key
19	nistFactory   *NISTFactory // Non-Interactive Session Token
20	secretSyncer  *SecretSyncer
21	passphrase    *PassphraseStreamCache
22	// This can be a paper key or a regular device key if we are self
23	// provisioning.
24	provisioningKey         *SelfDestructingDeviceWithKeys
25	secretPromptCancelTimer CancelTimer
26	keychainMode            KeychainMode
27	sync.RWMutex
28}
29
30func (a *ActiveDevice) Dump(m MetaContext, prefix string) {
31	m.Debug("%sActiveDevice: %p", prefix, a)
32	m.Debug("%sUserVersion: %+v", prefix, a.uv)
33	m.Debug("%sUsername (via env): %s", prefix, a.Username(m))
34	m.Debug("%sDeviceID: %s", prefix, a.deviceID)
35	m.Debug("%sDeviceName: %s", prefix, a.deviceName)
36	m.Debug("%sDeviceCtime: %s", prefix, keybase1.FormatTime(a.deviceCtime))
37	if a.signingKey != nil {
38		m.Debug("%sSigKey: %s", prefix, a.signingKey.GetKID())
39	}
40	if a.encryptionKey != nil {
41		m.Debug("%sEncKey: %s", prefix, a.encryptionKey.GetKID())
42	}
43	m.Debug("%sPassphraseCache: cacheObj=%v; valid=%v", prefix, (a.passphrase != nil), (a.passphrase != nil && a.passphrase.ValidPassphraseStream()))
44	m.Debug("%sProvisioningKeyCache: %v", prefix, (a.provisioningKey != nil && a.provisioningKey.DeviceWithKeys() != nil))
45	m.Debug("%sKeychainMode: %v", prefix, a.keychainMode)
46}
47
48// NewProvisionalActiveDevice creates an ActiveDevice that is "provisional", in
49// that it should not be considered the global ActiveDevice. Instead, it should
50// reside in thread-local context, and can be weaved through the login
51// machinery without trampling the actual global ActiveDevice.
52func NewProvisionalActiveDevice(m MetaContext, uv keybase1.UserVersion, d keybase1.DeviceID, sigKey GenericKey, encKey GenericKey, deviceName string, keychainMode KeychainMode) *ActiveDevice {
53	return &ActiveDevice{
54		uv:            uv,
55		deviceID:      d,
56		deviceName:    deviceName,
57		signingKey:    sigKey,
58		encryptionKey: encKey,
59		nistFactory:   NewNISTFactory(m.G(), uv.Uid, d, sigKey),
60		secretSyncer:  NewSecretSyncer(m.G()),
61		keychainMode:  keychainMode,
62	}
63}
64
65func NewActiveDevice() *ActiveDevice {
66	return &ActiveDevice{}
67}
68
69func NewProvisioningKeyActiveDevice(m MetaContext, uv keybase1.UserVersion, d *DeviceWithKeys) *ActiveDevice {
70	ret := NewActiveDeviceWithDeviceWithKeys(m, uv, d)
71	ret.provisioningKey = NewSelfDestructingDeviceWithKeys(m, d, ProvisioningKeyMemoryTimeout)
72	return ret
73}
74
75func NewActiveDeviceWithDeviceWithKeys(m MetaContext, uv keybase1.UserVersion, d *DeviceWithKeys) *ActiveDevice {
76	return &ActiveDevice{
77		uv:            uv,
78		deviceID:      d.deviceID,
79		deviceName:    d.deviceName,
80		signingKey:    d.signingKey,
81		encryptionKey: d.encryptionKey,
82		nistFactory:   NewNISTFactory(m.G(), uv.Uid, d.deviceID, d.signingKey),
83		secretSyncer:  NewSecretSyncer(m.G()),
84		keychainMode:  d.keychainMode,
85	}
86}
87
88func (a *ActiveDevice) ClearCaches() {
89	a.Lock()
90	defer a.Unlock()
91	a.passphrase = nil
92	a.provisioningKey = nil
93	a.secretPromptCancelTimer.Reset()
94}
95
96// Copy ActiveDevice info from the given ActiveDevice.
97func (a *ActiveDevice) Copy(m MetaContext, src *ActiveDevice) error {
98
99	// Take a consistent snapshot of the src device. Be careful not to hold
100	// locks on both devices at once.
101	src.Lock()
102	uv := src.uv
103	deviceID := src.deviceID
104	sigKey := src.signingKey
105	encKey := src.encryptionKey
106	name := src.deviceName
107	ctime := src.deviceCtime
108	keychainMode := src.keychainMode
109	src.Unlock()
110
111	return a.Set(m, uv, deviceID, sigKey, encKey, name, ctime, keychainMode)
112}
113
114func (a *ActiveDevice) SetOrClear(m MetaContext, a2 *ActiveDevice) error {
115	// Always clear, if we are also setting we set all new values.
116	err := a.Clear()
117	if err != nil {
118		return err
119	}
120	if a2 == nil {
121		return nil
122	}
123	return a.Copy(m, a2)
124}
125
126// Set acquires the write lock and sets all the fields in ActiveDevice.
127// The acct parameter is not used for anything except to help ensure
128// that this is called from inside a LoginState account request.
129func (a *ActiveDevice) Set(m MetaContext, uv keybase1.UserVersion, deviceID keybase1.DeviceID,
130	sigKey, encKey GenericKey, deviceName string, deviceCtime keybase1.Time, keychainMode KeychainMode) error {
131	a.Lock()
132	defer a.Unlock()
133
134	if err := a.internalUpdateUserVersionDeviceID(uv, deviceID); err != nil {
135		return err
136	}
137
138	a.signingKey = sigKey
139	a.encryptionKey = encKey
140	a.deviceName = deviceName
141	a.deviceCtime = deviceCtime
142	a.nistFactory = NewNISTFactory(m.G(), uv.Uid, deviceID, sigKey)
143	a.secretSyncer = NewSecretSyncer(m.G())
144	a.keychainMode = keychainMode
145
146	return nil
147}
148
149func (a *ActiveDevice) KeychainMode() KeychainMode {
150	a.Lock()
151	defer a.Unlock()
152	return a.keychainMode
153}
154
155// setSigningKey acquires the write lock and sets the signing key.
156// The acct parameter is not used for anything except to help ensure
157// that this is called from inside a LogingState account request.
158func (a *ActiveDevice) setSigningKey(g *GlobalContext, uv keybase1.UserVersion, deviceID keybase1.DeviceID,
159	sigKey GenericKey, deviceName string) error {
160	a.Lock()
161	defer a.Unlock()
162
163	if err := a.internalUpdateUserVersionDeviceID(uv, deviceID); err != nil {
164		return err
165	}
166
167	a.signingKey = sigKey
168	if len(deviceName) > 0 {
169		a.deviceName = deviceName
170	}
171	a.nistFactory = NewNISTFactory(g, uv.Uid, deviceID, sigKey)
172	return nil
173}
174
175// setEncryptionKey acquires the write lock and sets the encryption key.
176// The acct parameter is not used for anything except to help ensure
177// that this is called from inside a LogingState account request.
178func (a *ActiveDevice) setEncryptionKey(uv keybase1.UserVersion, deviceID keybase1.DeviceID, encKey GenericKey) error {
179	a.Lock()
180	defer a.Unlock()
181
182	if err := a.internalUpdateUserVersionDeviceID(uv, deviceID); err != nil {
183		return err
184	}
185
186	a.encryptionKey = encKey
187	return nil
188}
189
190// should only called by the functions in this type, with the write lock.
191func (a *ActiveDevice) internalUpdateUserVersionDeviceID(uv keybase1.UserVersion, deviceID keybase1.DeviceID) error {
192
193	if uv.IsNil() {
194		return errors.New("ActiveDevice.set with nil uid")
195	}
196	if deviceID.IsNil() {
197		return errors.New("ActiveDevice.set with nil deviceID")
198	}
199
200	if a.uv.IsNil() && a.deviceID.IsNil() {
201		a.uv = uv
202		a.deviceID = deviceID
203	} else if !a.uv.Eq(uv) {
204		return errors.New("ActiveDevice.set uid mismatch")
205	} else if !a.deviceID.Eq(deviceID) {
206		return errors.New("ActiveDevice.set deviceID mismatch")
207	}
208
209	return nil
210}
211
212func (a *ActiveDevice) Clear() error {
213	_, err := a.clear()
214	return err
215}
216
217func (a *ActiveDevice) ClearGetKeychainMode() (KeychainMode, error) {
218	return a.clear()
219}
220
221// Clear acquires the write lock and resets all the fields to zero values.
222func (a *ActiveDevice) clear() (KeychainMode, error) {
223	a.Lock()
224	defer a.Unlock()
225
226	a.uv = keybase1.UserVersion{}
227	a.deviceID = ""
228	a.deviceName = ""
229	a.signingKey = nil
230	a.encryptionKey = nil
231	a.nistFactory = nil
232	a.passphrase = nil
233	a.provisioningKey = nil
234	a.secretPromptCancelTimer.Reset()
235	ret := a.keychainMode
236	a.keychainMode = KeychainModeNone
237	return ret, nil
238}
239
240func (a *ActiveDevice) SecretPromptCancelTimer() *CancelTimer {
241	a.RLock()
242	defer a.RUnlock()
243	return &a.secretPromptCancelTimer
244}
245
246// UID returns the user ID that was provided when the device keys were cached.
247// Safe for use by concurrent goroutines.
248func (a *ActiveDevice) UID() keybase1.UID {
249	a.RLock()
250	defer a.RUnlock()
251	return a.uv.Uid
252}
253
254func (a *ActiveDevice) UIDAndEncryptionKey() (keybase1.UID, GenericKey) {
255	a.RLock()
256	defer a.RUnlock()
257	return a.uv.Uid, a.encryptionKey
258}
259
260func (a *ActiveDevice) UserVersion() keybase1.UserVersion {
261	a.RLock()
262	defer a.RUnlock()
263	return a.uv
264}
265
266// Username tries to get the active user's username by looking into the current
267// environment and mapping an UID to a username based on our config file. It
268// won't work halfway through a provisioning.
269func (a *ActiveDevice) Username(m MetaContext) NormalizedUsername {
270	return m.G().Env.GetUsernameForUID(a.UID())
271}
272
273// DeviceID returns the device ID that was provided when the device keys were
274// cached.  Safe for use by concurrent goroutines.
275func (a *ActiveDevice) DeviceID() keybase1.DeviceID {
276	a.RLock()
277	defer a.RUnlock()
278	return a.deviceID
279}
280
281func (a *ActiveDevice) DeviceType(mctx MetaContext) (keybase1.DeviceTypeV2, error) {
282	if a.secretSyncer.keys == nil {
283		mctx.Debug("keys are not synced with the server for this ActiveDevice. lets do that right now")
284		_, err := a.SyncSecretsForce(mctx)
285		if err != nil {
286			return keybase1.DeviceTypeV2_NONE, err
287		}
288	}
289	devices, err := a.secretSyncer.Devices()
290	if err != nil {
291		return keybase1.DeviceTypeV2_NONE, err
292	}
293	for devID, dev := range devices {
294		if devID == a.DeviceID() {
295			return dev.Type, nil
296		}
297	}
298	return keybase1.DeviceTypeV2_NONE, NotFoundError{
299		Msg: "Not found: device type",
300	}
301}
302
303// SigningKey returns the signing key for the active device.
304// Safe for use by concurrent goroutines.
305func (a *ActiveDevice) SigningKey() (GenericKey, error) {
306	a.RLock()
307	defer a.RUnlock()
308	if a.signingKey == nil {
309		return nil, NotFoundError{
310			Msg: "Not found: device signing key",
311		}
312	}
313	return a.signingKey, nil
314}
315
316// SigningKeyWithUID returns the signing key for the active device.
317// Returns an error if uid is not active.
318// Safe for use by concurrent goroutines.
319func (a *ActiveDevice) SigningKeyWithUID(uid keybase1.UID) (GenericKey, error) {
320	a.RLock()
321	defer a.RUnlock()
322	if a.uv.Uid.IsNil() {
323		return nil, NotFoundError{
324			Msg: "Not found: device signing key (no active user)",
325		}
326	}
327	if a.uv.Uid != uid {
328		return nil, fmt.Errorf("device signing key for non-active user: %v != %v", a.uv.Uid, uid)
329	}
330	if a.signingKey == nil {
331		return nil, NotFoundError{
332			Msg: "Not found: device signing key",
333		}
334	}
335	return a.signingKey, nil
336}
337
338// EncryptionKey returns the encryption key for the active device.
339// Safe for use by concurrent goroutines.
340func (a *ActiveDevice) EncryptionKey() (GenericKey, error) {
341	a.RLock()
342	defer a.RUnlock()
343	if a.encryptionKey == nil {
344		return nil, NotFoundError{
345			Msg: "Not found: device encryption key",
346		}
347	}
348	return a.encryptionKey, nil
349}
350
351// EncryptionKeyWithUID returns the encryption key for the active device.
352// Returns an error if uid is not active.
353// Safe for use by concurrent goroutines.
354func (a *ActiveDevice) EncryptionKeyWithUID(uid keybase1.UID) (GenericKey, error) {
355	a.RLock()
356	defer a.RUnlock()
357	if a.uv.Uid.IsNil() {
358		return nil, NotFoundError{
359			Msg: "Not found: device encryption key (no active user)",
360		}
361	}
362	if a.uv.Uid != uid {
363		return nil, fmt.Errorf("device encryption key for non-active user: %v != %v", a.uv.Uid, uid)
364	}
365	if a.encryptionKey == nil {
366		return nil, NotFoundError{
367			Msg: "Not found: device encryption key",
368		}
369	}
370	return a.encryptionKey, nil
371}
372
373// NaclEncryptionKey returns the encryption key for the active device, as a
374// NaclDHKeyPair. If the cast fails (though that should never happen), it
375// returns an error.
376func (a *ActiveDevice) NaclEncryptionKey() (*NaclDHKeyPair, error) {
377	genericKey, err := a.EncryptionKey()
378	if err != nil {
379		return nil, err
380	}
381	naclKey, ok := genericKey.(NaclDHKeyPair)
382	if !ok {
383		return nil, fmt.Errorf("expected NaclDHKeyPair, got %T", genericKey)
384	}
385	return &naclKey, nil
386}
387
388// KeyByType returns a cached key based on SecretKeyType.
389// Safe for use by concurrent goroutines.
390func (a *ActiveDevice) KeyByType(t SecretKeyType) (GenericKey, error) {
391	switch t {
392	case DeviceSigningKeyType:
393		return a.SigningKey()
394	case DeviceEncryptionKeyType:
395		return a.EncryptionKey()
396	default:
397		return nil, fmt.Errorf("Invalid type %v", t)
398	}
399}
400
401// KeyByTypeWithUID is like KeyByType but returns an error if uid is not active.
402// Safe for use by concurrent goroutines.
403func (a *ActiveDevice) KeyByTypeWithUID(uid keybase1.UID, t SecretKeyType) (GenericKey, error) {
404	switch t {
405	case DeviceSigningKeyType:
406		return a.SigningKeyWithUID(uid)
407	case DeviceEncryptionKeyType:
408		return a.EncryptionKeyWithUID(uid)
409	default:
410		return nil, fmt.Errorf("Invalid type %v", t)
411	}
412}
413
414// AllFields returns all the ActiveDevice fields via one lock for consistency.
415// Safe for use by concurrent goroutines.
416func (a *ActiveDevice) AllFields() (uv keybase1.UserVersion, deviceID keybase1.DeviceID, deviceName string, sigKey GenericKey, encKey GenericKey) {
417	a.RLock()
418	defer a.RUnlock()
419
420	return a.uv, a.deviceID, a.deviceName, a.signingKey, a.encryptionKey
421}
422
423func (a *ActiveDevice) Name() string {
424	a.RLock()
425	defer a.RUnlock()
426
427	return a.deviceName
428}
429
430func (a *ActiveDevice) HaveKeys() bool {
431	a.RLock()
432	defer a.RUnlock()
433
434	return a.signingKey != nil && a.encryptionKey != nil
435}
436
437func (a *ActiveDevice) Valid() bool {
438	a.RLock()
439	defer a.RUnlock()
440
441	return a.valid()
442}
443
444func (a *ActiveDevice) valid() bool {
445	return a.signingKey != nil && a.encryptionKey != nil && !a.uv.IsNil() && !a.deviceID.IsNil() && a.deviceName != ""
446}
447
448func (a *ActiveDevice) Ctime(m MetaContext) (keybase1.Time, error) {
449	// make sure the device id doesn't change throughout this function
450	deviceID := a.DeviceID()
451
452	// check if we have a cached ctime already
453	ctime, err := a.ctimeCached(deviceID)
454	if err != nil {
455		return 0, err
456	}
457	if ctime > 0 {
458		return ctime, nil
459	}
460
461	// need to build a device and ask the server for ctimes
462	decKeys, err := a.deviceKeys(deviceID)
463	if err != nil {
464		return 0, err
465	}
466	// Note: decKeys.Populate() makes a network API call
467	if _, err := decKeys.Populate(m); err != nil {
468		return 0, nil
469	}
470
471	// set the ctime value under a write lock
472	a.Lock()
473	defer a.Unlock()
474	if !a.deviceID.Eq(deviceID) {
475		return 0, errors.New("active device changed during ctime lookup")
476	}
477	a.deviceCtime = decKeys.DeviceCtime()
478
479	return a.deviceCtime, nil
480}
481
482func (a *ActiveDevice) ctimeCached(deviceID keybase1.DeviceID) (keybase1.Time, error) {
483	a.RLock()
484	defer a.RUnlock()
485
486	if !a.deviceID.Eq(deviceID) {
487		return 0, errors.New("active device changed during ctime lookup")
488	}
489
490	return a.deviceCtime, nil
491}
492
493func (a *ActiveDevice) deviceKeys(deviceID keybase1.DeviceID) (*DeviceWithKeys, error) {
494	a.RLock()
495	defer a.RUnlock()
496
497	if !a.valid() {
498		return nil, errors.New("active device is not valid")
499	}
500
501	if !a.deviceID.Eq(deviceID) {
502		return nil, errors.New("active device changed")
503	}
504
505	return NewDeviceWithKeysOnly(a.signingKey, a.encryptionKey, a.keychainMode), nil
506}
507
508func (a *ActiveDevice) DeviceKeys() (*DeviceWithKeys, error) {
509	a.RLock()
510	defer a.RUnlock()
511
512	if !a.valid() {
513		return nil, errors.New("active device is not valid")
514	}
515	return NewDeviceWithKeysOnly(a.signingKey, a.encryptionKey, a.keychainMode), nil
516}
517
518func (a *ActiveDevice) IsValidFor(uid keybase1.UID, deviceID keybase1.DeviceID) bool {
519	a.RLock()
520	defer a.RUnlock()
521	if a.signingKey == nil || a.encryptionKey == nil {
522		return false
523	}
524	if !uid.Equal(a.uv.Uid) {
525		return false
526	}
527	if !deviceID.Eq(a.deviceID) {
528		return false
529	}
530	return true
531}
532
533func (a *ActiveDevice) NIST(ctx context.Context) (*NIST, error) {
534	a.RLock()
535	defer a.RUnlock()
536	return a.nistLocked(ctx)
537}
538
539func (a *ActiveDevice) NISTWebAuthToken(ctx context.Context) (*NIST, error) {
540	a.RLock()
541	defer a.RUnlock()
542	return a.nistFactory.GenerateWebAuthToken(ctx)
543}
544
545func (a *ActiveDevice) nistLocked(ctx context.Context) (*NIST, error) {
546	nist, err := a.nistFactory.NIST(ctx)
547	if err != nil {
548		return nil, err
549	}
550	if nist == nil {
551		return nil, nil
552	}
553	uid := a.nistFactory.UID()
554	if !uid.Equal(a.uv.Uid) {
555		return nil, NewUIDMismatchError(fmt.Sprintf("NIST generation error, UIDs didn't match; ActiveDevice said %s, but NIST factory said %s", a.uv.Uid, uid))
556	}
557
558	return nist, nil
559}
560
561func (a *ActiveDevice) NISTAndUIDDeviceID(ctx context.Context) (*NIST, keybase1.UID, keybase1.DeviceID, error) {
562	a.RLock()
563	defer a.RUnlock()
564	nist, err := a.nistLocked(ctx)
565	return nist, a.uv.Uid, a.deviceID, err
566}
567
568func (a *ActiveDevice) SyncSecretsForUID(m MetaContext, u keybase1.UID, force bool) (ret *SecretSyncer, err error) {
569	defer m.Trace("ActiveDevice#SyncSecretsForUID", &err)()
570
571	a.RLock()
572	s := a.secretSyncer
573	uid := a.uv.Uid
574	a.RUnlock()
575
576	if !u.IsNil() && !uid.Equal(u) {
577		return nil, fmt.Errorf("Wrong UID for sync secrets: %s != %s", uid, u)
578	}
579	if s == nil {
580		return nil, fmt.Errorf("Can't sync secrets: nil secret syncer")
581	}
582	if uid.IsNil() {
583		return nil, fmt.Errorf("can't run secret syncer without a UID")
584	}
585	if err = RunSyncer(m, s, uid, true, force); err != nil {
586		return nil, err
587	}
588	return s, nil
589}
590
591func (a *ActiveDevice) SyncSecrets(m MetaContext) (ret *SecretSyncer, err error) {
592	defer m.Trace("ActiveDevice#SyncSecrets", &err)()
593	var zed keybase1.UID
594	return a.SyncSecretsForUID(m, zed, false /* force */)
595}
596
597func (a *ActiveDevice) SyncSecretsForce(m MetaContext) (ret *SecretSyncer, err error) {
598	defer m.Trace("ActiveDevice#SyncSecretsForce", &err)()
599	var zed keybase1.UID
600	return a.SyncSecretsForUID(m, zed, true /* force */)
601}
602
603func (a *ActiveDevice) CheckForUsername(m MetaContext, n NormalizedUsername, suppressNetworkErrors bool) (err error) {
604	a.RLock()
605	uid := a.uv.Uid
606	deviceID := a.deviceID
607	valid := a.valid()
608	a.RUnlock()
609	if !valid {
610		return NoActiveDeviceError{}
611	}
612	return m.G().GetUPAKLoader().CheckDeviceForUIDAndUsername(m.Ctx(), uid, deviceID, n, suppressNetworkErrors)
613}
614
615func (a *ActiveDevice) ProvisioningKeyWrapper(m MetaContext) *SelfDestructingDeviceWithKeys {
616	a.RLock()
617	defer a.RUnlock()
618	return a.provisioningKey
619}
620
621func (a *ActiveDevice) ProvisioningKey(m MetaContext) *DeviceWithKeys {
622	a.RLock()
623	defer a.RUnlock()
624	if a.provisioningKey == nil {
625		return nil
626	}
627	return a.provisioningKey.DeviceWithKeys()
628}
629
630func (a *ActiveDevice) ClearProvisioningKey(m MetaContext) {
631	a.Lock()
632	defer a.Unlock()
633	a.provisioningKey = nil
634}
635
636func (a *ActiveDevice) CacheProvisioningKey(m MetaContext, k *DeviceWithKeys) {
637	a.Lock()
638	defer a.Unlock()
639	a.provisioningKey = NewSelfDestructingDeviceWithKeys(m, k, ProvisioningKeyMemoryTimeout)
640}
641
642func (a *ActiveDevice) PassphraseStreamCache() *PassphraseStreamCache {
643	a.RLock()
644	defer a.RUnlock()
645	return a.passphrase
646}
647
648func (a *ActiveDevice) PassphraseStream() *PassphraseStream {
649	a.RLock()
650	defer a.RUnlock()
651	c := a.PassphraseStreamCache()
652	if c == nil || !c.ValidPassphraseStream() {
653		return nil
654	}
655	return c.PassphraseStream()
656}
657
658func (a *ActiveDevice) TriplesecAndGeneration() (Triplesec, PassphraseGeneration) {
659	a.RLock()
660	defer a.RUnlock()
661	var zed PassphraseGeneration
662	c := a.PassphraseStreamCache()
663	if c == nil {
664		return nil, zed
665	}
666	return c.TriplesecAndGeneration()
667}
668
669func (a *ActiveDevice) CachePassphraseStream(c *PassphraseStreamCache) {
670	a.Lock()
671	defer a.Unlock()
672	a.passphrase = c
673}
674
675func (a *ActiveDevice) ClearPassphraseStreamCache() {
676	a.Lock()
677	defer a.Unlock()
678	a.passphrase = nil
679}
680
681func (a *ActiveDevice) ClearPassphraseStreamCacheIfOutdated(mctx MetaContext) error {
682	pps := a.PassphraseStream()
683	if pps == nil {
684		return nil
685	}
686
687	outdated, err := pps.SyncAndCheckIfOutdated(mctx)
688	if err != nil {
689		return err
690	}
691
692	if outdated {
693		a.ClearPassphraseStreamCache()
694	}
695	return nil
696}
697
698func (a *ActiveDevice) SigningKeyForUID(u keybase1.UID) GenericKey {
699	a.RLock()
700	defer a.RUnlock()
701	if !a.UID().Equal(u) {
702		return nil
703	}
704	return a.signingKey
705}
706
707func (a *ActiveDevice) Keyring(m MetaContext) (ret *SKBKeyringFile, err error) {
708	defer m.Trace("ActiveDevice#Keyring", &err)()
709	un := a.Username(m)
710	if un.IsNil() {
711		return nil, NewNoUsernameError()
712	}
713	m.Debug("Account: loading keyring for %s", un)
714	ret, err = LoadSKBKeyring(m, un)
715	if err != nil {
716		return nil, err
717	}
718	return ret, nil
719}
720
721func (a *ActiveDevice) CopyCacheToLoginContextIfForUserVersion(m MetaContext, lc LoginContext, uv keybase1.UserVersion) (err error) {
722	defer m.Trace("ActiveDevice#CopyCacheToLoginContextIfForUID", &err)()
723	a.RLock()
724	defer a.RUnlock()
725	if !a.uv.Eq(uv) {
726		return NewUIDMismatchError(fmt.Sprintf("%s v %s", a.uv, uv))
727	}
728	if a.passphrase != nil {
729		m.Debug("| copying non-nil passphrase cache")
730		lc.SetStreamCache(a.passphrase)
731	}
732	return nil
733}
734
735func (a *ActiveDevice) GetUsernameAndUserVersionIfValid(m MetaContext) (uv keybase1.UserVersion, un NormalizedUsername) {
736	a.RLock()
737	defer a.RUnlock()
738	if a.uv.IsNil() {
739		return uv, un
740	}
741	un = m.G().Env.GetUsernameForUID(a.uv.Uid)
742	if un.IsNil() {
743		return keybase1.UserVersion{}, NormalizedUsername("")
744	}
745	return a.uv, un
746}
747