github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libkb/active_device.go (about)

     1  package libkb
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"sync"
     7  
     8  	"github.com/keybase/client/go/protocol/keybase1"
     9  	context "golang.org/x/net/context"
    10  )
    11  
    12  type 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  
    30  func (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.
    52  func 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  
    65  func NewActiveDevice() *ActiveDevice {
    66  	return &ActiveDevice{}
    67  }
    68  
    69  func 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  
    75  func 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  
    88  func (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.
    97  func (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  
   114  func (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.
   129  func (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  
   149  func (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.
   158  func (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.
   178  func (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.
   191  func (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  
   212  func (a *ActiveDevice) Clear() error {
   213  	_, err := a.clear()
   214  	return err
   215  }
   216  
   217  func (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.
   222  func (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  
   240  func (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.
   248  func (a *ActiveDevice) UID() keybase1.UID {
   249  	a.RLock()
   250  	defer a.RUnlock()
   251  	return a.uv.Uid
   252  }
   253  
   254  func (a *ActiveDevice) UIDAndEncryptionKey() (keybase1.UID, GenericKey) {
   255  	a.RLock()
   256  	defer a.RUnlock()
   257  	return a.uv.Uid, a.encryptionKey
   258  }
   259  
   260  func (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.
   269  func (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.
   275  func (a *ActiveDevice) DeviceID() keybase1.DeviceID {
   276  	a.RLock()
   277  	defer a.RUnlock()
   278  	return a.deviceID
   279  }
   280  
   281  func (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.
   305  func (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.
   319  func (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.
   340  func (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.
   354  func (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.
   376  func (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.
   390  func (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.
   403  func (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.
   416  func (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  
   423  func (a *ActiveDevice) Name() string {
   424  	a.RLock()
   425  	defer a.RUnlock()
   426  
   427  	return a.deviceName
   428  }
   429  
   430  func (a *ActiveDevice) HaveKeys() bool {
   431  	a.RLock()
   432  	defer a.RUnlock()
   433  
   434  	return a.signingKey != nil && a.encryptionKey != nil
   435  }
   436  
   437  func (a *ActiveDevice) Valid() bool {
   438  	a.RLock()
   439  	defer a.RUnlock()
   440  
   441  	return a.valid()
   442  }
   443  
   444  func (a *ActiveDevice) valid() bool {
   445  	return a.signingKey != nil && a.encryptionKey != nil && !a.uv.IsNil() && !a.deviceID.IsNil() && a.deviceName != ""
   446  }
   447  
   448  func (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  
   482  func (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  
   493  func (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  
   508  func (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  
   518  func (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  
   533  func (a *ActiveDevice) NIST(ctx context.Context) (*NIST, error) {
   534  	a.RLock()
   535  	defer a.RUnlock()
   536  	return a.nistLocked(ctx)
   537  }
   538  
   539  func (a *ActiveDevice) NISTWebAuthToken(ctx context.Context) (*NIST, error) {
   540  	a.RLock()
   541  	defer a.RUnlock()
   542  	return a.nistFactory.GenerateWebAuthToken(ctx)
   543  }
   544  
   545  func (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  
   561  func (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  
   568  func (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  
   591  func (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  
   597  func (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  
   603  func (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  
   615  func (a *ActiveDevice) ProvisioningKeyWrapper(m MetaContext) *SelfDestructingDeviceWithKeys {
   616  	a.RLock()
   617  	defer a.RUnlock()
   618  	return a.provisioningKey
   619  }
   620  
   621  func (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  
   630  func (a *ActiveDevice) ClearProvisioningKey(m MetaContext) {
   631  	a.Lock()
   632  	defer a.Unlock()
   633  	a.provisioningKey = nil
   634  }
   635  
   636  func (a *ActiveDevice) CacheProvisioningKey(m MetaContext, k *DeviceWithKeys) {
   637  	a.Lock()
   638  	defer a.Unlock()
   639  	a.provisioningKey = NewSelfDestructingDeviceWithKeys(m, k, ProvisioningKeyMemoryTimeout)
   640  }
   641  
   642  func (a *ActiveDevice) PassphraseStreamCache() *PassphraseStreamCache {
   643  	a.RLock()
   644  	defer a.RUnlock()
   645  	return a.passphrase
   646  }
   647  
   648  func (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  
   658  func (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  
   669  func (a *ActiveDevice) CachePassphraseStream(c *PassphraseStreamCache) {
   670  	a.Lock()
   671  	defer a.Unlock()
   672  	a.passphrase = c
   673  }
   674  
   675  func (a *ActiveDevice) ClearPassphraseStreamCache() {
   676  	a.Lock()
   677  	defer a.Unlock()
   678  	a.passphrase = nil
   679  }
   680  
   681  func (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  
   698  func (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  
   707  func (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  
   721  func (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  
   735  func (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  }