github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/ephemeral/device_ek_storage.go (about)

     1  package ephemeral
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"sort"
     7  	"strconv"
     8  	"strings"
     9  	"sync"
    10  	"time"
    11  
    12  	"github.com/keybase/client/go/libkb"
    13  	"github.com/keybase/client/go/logger"
    14  	keybase1 "github.com/keybase/client/go/protocol/keybase1"
    15  )
    16  
    17  const (
    18  	deviceEKSubDir = "device-eks"
    19  	deviceEKPrefix = "deviceEphemeralKey"
    20  	deviceEKSuffix = ".ek"
    21  )
    22  
    23  type deviceEKCacheItem struct {
    24  	DeviceEK keybase1.DeviceEk
    25  	Err      error
    26  }
    27  
    28  type deviceEKCache map[keybase1.EkGeneration]deviceEKCacheItem
    29  type DeviceEKMap map[keybase1.EkGeneration]keybase1.DeviceEk
    30  
    31  type DeviceEKStorage struct {
    32  	sync.Mutex
    33  	storage libkb.ErasableKVStore
    34  	cache   deviceEKCache
    35  	indexed bool
    36  	logger  *log.Logger
    37  }
    38  
    39  func getLogger(mctx libkb.MetaContext) *log.Logger {
    40  	filename := mctx.G().Env.GetEKLogFile()
    41  	lfc := mctx.G().Env.GetLogFileConfig(filename)
    42  	lfc.SkipRedirectStdErr = true
    43  	lfw := logger.NewLogFileWriter(*lfc)
    44  	if err := lfw.Open(mctx.G().GetClock().Now()); err != nil {
    45  		mctx.Debug("Unable to getLogger %v", err)
    46  		return nil
    47  	}
    48  	l := log.New(lfw, getLogPrefix(mctx), log.LstdFlags|log.Lmicroseconds|log.Lshortfile)
    49  	return l
    50  }
    51  
    52  func getLogPrefix(mctx libkb.MetaContext) string {
    53  	return fmt.Sprintf("[username=%v] ", mctx.G().Env.GetUsername())
    54  }
    55  
    56  func getLocalStorageSecretBoxKey(mctx libkb.MetaContext) (fkey [32]byte, err error) {
    57  	// Get secret device key
    58  	encKey, err := mctx.ActiveDevice().EncryptionKey()
    59  	if err != nil {
    60  		return fkey, err
    61  	}
    62  	kp, ok := encKey.(libkb.NaclDHKeyPair)
    63  	if !ok || kp.Private == nil {
    64  		return fkey, libkb.KeyCannotDecryptError{}
    65  	}
    66  
    67  	// Derive symmetric key from device key
    68  	skey, err := encKey.SecretSymmetricKey(libkb.EncryptionReasonErasableKVLocalStorage)
    69  	if err != nil {
    70  		return fkey, err
    71  	}
    72  
    73  	copy(fkey[:], skey[:])
    74  	return fkey, nil
    75  }
    76  
    77  func deviceEKKeygen(mctx libkb.MetaContext, noiseBytes libkb.NoiseBytes) (fkey [32]byte, err error) {
    78  	enckey, err := getLocalStorageSecretBoxKey(mctx)
    79  	if err != nil {
    80  		return fkey, err
    81  	}
    82  
    83  	xor, err := libkb.NoiseXOR(enckey, noiseBytes)
    84  	if err != nil {
    85  		return fkey, err
    86  	}
    87  	copy(fkey[:], xor)
    88  	return fkey, nil
    89  }
    90  
    91  func NewDeviceEKStorage(mctx libkb.MetaContext) *DeviceEKStorage {
    92  	return &DeviceEKStorage{
    93  		storage: libkb.NewFileErasableKVStore(mctx, deviceEKSubDir, deviceEKKeygen),
    94  		cache:   make(deviceEKCache),
    95  		logger:  getLogger(mctx),
    96  	}
    97  }
    98  
    99  func (s *DeviceEKStorage) SetLogPrefix(mctx libkb.MetaContext) {
   100  	s.Lock()
   101  	defer s.Unlock()
   102  	if s.logger != nil {
   103  		s.logger.SetPrefix(getLogPrefix(mctx))
   104  	}
   105  }
   106  
   107  // Log sensitive deletion actions to a separate log file so we don't lose the
   108  // logs during normal rotation.
   109  func (s *DeviceEKStorage) ekLogf(mctx libkb.MetaContext, format string, args ...interface{}) {
   110  	mctx.Debug(format, args...)
   111  	if s.logger != nil {
   112  		s.logger.Printf(format, args...)
   113  	}
   114  }
   115  
   116  func (s *DeviceEKStorage) ekLogCTrace(mctx libkb.MetaContext, msg string, err *error) func() {
   117  	if s.logger != nil {
   118  		s.logger.Print(msg)
   119  	}
   120  	return mctx.Trace(msg, err)
   121  }
   122  
   123  func (s *DeviceEKStorage) keyPrefixFromUsername(username libkb.NormalizedUsername) string {
   124  	return fmt.Sprintf("%s-%s-", deviceEKPrefix, username)
   125  }
   126  
   127  func (s *DeviceEKStorage) keyPrefix(mctx libkb.MetaContext) (prefix string, err error) {
   128  	uv, err := mctx.G().GetMeUV(mctx.Ctx())
   129  	if err != nil {
   130  		return prefix, err
   131  	}
   132  	username := mctx.ActiveDevice().Username(mctx)
   133  	return fmt.Sprintf("%s%s-", s.keyPrefixFromUsername(username), uv.EldestSeqno), nil
   134  }
   135  
   136  func (s *DeviceEKStorage) key(mctx libkb.MetaContext, generation keybase1.EkGeneration) (key string, err error) {
   137  	prefix, err := s.keyPrefix(mctx)
   138  	if err != nil {
   139  		return key, err
   140  	}
   141  	return fmt.Sprintf("%s%d%s", prefix, generation, deviceEKSuffix), nil
   142  }
   143  
   144  // keyToEldestSeqno parses out the `eldestSeqno` from a key of the form
   145  // deviceEKPrefix-username-eldestSeqno-generation.ek. If we have a key for a
   146  // eldestSeqno that is not our current, we purge it since we don't want the
   147  // ephemeral key to stick around if we've reset. If we are unable to parse out
   148  // the value, the key is not valid, or not for the logged in user we return -1
   149  func (s *DeviceEKStorage) keyToEldestSeqno(mctx libkb.MetaContext, key string) keybase1.Seqno {
   150  	if !strings.HasPrefix(key, deviceEKPrefix) {
   151  		return -1
   152  	}
   153  	parts := strings.Split(key, "-")
   154  	if len(parts) != 4 {
   155  		return -1
   156  	}
   157  	// Make sure this key is for our current user and not a different one.
   158  	username := mctx.ActiveDevice().Username(mctx)
   159  	if parts[1] != username.String() {
   160  		return -1
   161  	}
   162  	e, err := strconv.ParseUint(parts[2], 10, 64)
   163  	if err != nil {
   164  		return -1
   165  	}
   166  	return keybase1.Seqno(e)
   167  }
   168  
   169  // keyToEldestSeqno parses out the `generation` from a key of the form
   170  // deviceEKPrefix-username-eldestSeqno-generation.ek. Unparseable keys return a
   171  // generation of -1 and should be ignored.
   172  func (s *DeviceEKStorage) keyToGeneration(mctx libkb.MetaContext, key string) keybase1.EkGeneration {
   173  	prefix, err := s.keyPrefix(mctx)
   174  	if err != nil {
   175  		mctx.Debug("keyToGeneration: unable to get keyPrefix: %v", err)
   176  		return -1
   177  	}
   178  	if !strings.HasPrefix(key, prefix) || !strings.HasSuffix(key, deviceEKSuffix) {
   179  		mctx.Debug("keyToGeneration: key missing prefix: %v or suffix: %s", prefix, deviceEKSuffix)
   180  		return -1
   181  	}
   182  
   183  	key = strings.TrimSuffix(key, deviceEKSuffix)
   184  	parts := strings.Split(key, prefix)
   185  	if len(parts) != 2 {
   186  		mctx.Debug("keyToGeneration: unexpected parts: %v, prefix: %v", parts)
   187  		return -1
   188  	}
   189  	g, err := strconv.ParseUint(parts[1], 10, 64)
   190  	if err != nil {
   191  		mctx.Debug("keyToGeneration: unable to parseUint: %v", err)
   192  		return -1
   193  	}
   194  	return keybase1.EkGeneration(g)
   195  }
   196  
   197  func (s *DeviceEKStorage) Put(mctx libkb.MetaContext, generation keybase1.EkGeneration, deviceEK keybase1.DeviceEk) (err error) {
   198  	defer mctx.Trace(fmt.Sprintf("DeviceEKStorage#Put: generation:%v", generation), &err)()
   199  
   200  	s.Lock()
   201  	defer s.Unlock()
   202  
   203  	// sanity check that we got the right generation
   204  	if deviceEK.Metadata.Generation != generation {
   205  		return newEKCorruptedErr(mctx, DeviceEKKind, generation, deviceEK.Metadata.Generation)
   206  	}
   207  
   208  	key, err := s.key(mctx, generation)
   209  	if err != nil {
   210  		return err
   211  	}
   212  	// Fill in this puppy.
   213  	if deviceEK.Metadata.DeviceCtime == 0 {
   214  		deviceEK.Metadata.DeviceCtime = keybase1.ToTime(time.Now())
   215  	}
   216  	if err = s.storage.Put(mctx, key, deviceEK); err != nil {
   217  		return err
   218  	}
   219  
   220  	// cache the result
   221  	cache, err := s.getCache(mctx)
   222  	if err != nil {
   223  		return err
   224  	}
   225  	cache[generation] = deviceEKCacheItem{
   226  		DeviceEK: deviceEK,
   227  		Err:      nil,
   228  	}
   229  	return nil
   230  }
   231  
   232  func (s *DeviceEKStorage) Get(mctx libkb.MetaContext, generation keybase1.EkGeneration) (deviceEK keybase1.DeviceEk, err error) {
   233  	defer mctx.Trace(fmt.Sprintf("DeviceEKStorage#Get: generation:%v", generation), &err)()
   234  	s.Lock()
   235  	defer s.Unlock()
   236  
   237  	// Try the cache first
   238  	cache, err := s.getCache(mctx)
   239  	if err != nil {
   240  		return deviceEK, err
   241  	}
   242  	cacheItem, ok := cache[generation]
   243  	if ok {
   244  		return cacheItem.DeviceEK, cacheItem.Err
   245  	}
   246  	// Try persistent storage.
   247  	deviceEK, err = s.get(mctx, generation)
   248  	switch err.(type) {
   249  	case nil, libkb.UnboxError:
   250  		// cache the result
   251  		cache[generation] = deviceEKCacheItem{
   252  			DeviceEK: deviceEK,
   253  			Err:      err,
   254  		}
   255  		return deviceEK, err
   256  	default:
   257  		return deviceEK, err
   258  	}
   259  }
   260  
   261  func (s *DeviceEKStorage) get(mctx libkb.MetaContext, generation keybase1.EkGeneration) (deviceEK keybase1.DeviceEk, err error) {
   262  	defer mctx.Trace(fmt.Sprintf("DeviceEKStorage#get: generation:%v", generation), &err)()
   263  
   264  	key, err := s.key(mctx, generation)
   265  	if err != nil {
   266  		return deviceEK, err
   267  	}
   268  
   269  	if err = s.storage.Get(mctx, key, &deviceEK); err != nil {
   270  		if _, ok := err.(libkb.UnboxError); ok {
   271  			s.ekLogf(mctx, "DeviceEKStorage#get: corrupted generation: %v -> %v: %v", key, generation, err)
   272  			if ierr := s.storage.Erase(mctx, key); ierr != nil {
   273  				s.ekLogf(mctx, "DeviceEKStorage#get: unable to delete corrupted generation: %v", ierr)
   274  			}
   275  		}
   276  		return deviceEK, err
   277  	}
   278  	// sanity check that we got the right generation
   279  	if deviceEK.Metadata.Generation != generation {
   280  		return deviceEK, newEKCorruptedErr(mctx, DeviceEKKind, generation, deviceEK.Metadata.Generation)
   281  	}
   282  	return deviceEK, nil
   283  }
   284  
   285  func (s *DeviceEKStorage) Delete(mctx libkb.MetaContext, generation keybase1.EkGeneration,
   286  	reason string, args ...interface{}) (err error) {
   287  	s.Lock()
   288  	defer s.Unlock()
   289  	return s.delete(mctx, generation, reason, args...)
   290  }
   291  
   292  func (s *DeviceEKStorage) delete(mctx libkb.MetaContext, generation keybase1.EkGeneration,
   293  	reason string, args ...interface{}) (err error) {
   294  	defer s.ekLogCTrace(mctx, fmt.Sprintf("DeviceEKStorage#delete: generation:%v reason: %s", generation, fmt.Sprintf(reason, args...)), &err)()
   295  
   296  	// clear the cache
   297  	cache, err := s.getCache(mctx)
   298  	if err != nil {
   299  		return err
   300  	}
   301  	key, err := s.key(mctx, generation)
   302  	if err != nil {
   303  		return err
   304  	}
   305  	if err = s.storage.Erase(mctx, key); err != nil {
   306  		return err
   307  	}
   308  	delete(cache, generation)
   309  	return nil
   310  }
   311  
   312  func (s *DeviceEKStorage) getCache(mctx libkb.MetaContext) (cache deviceEKCache, err error) {
   313  	if !s.indexed {
   314  		keys, err := s.storage.AllKeys(mctx, deviceEKSuffix)
   315  		if err != nil {
   316  			return nil, err
   317  		}
   318  		for _, key := range keys {
   319  			generation := s.keyToGeneration(mctx, key)
   320  			if generation < 0 {
   321  				mctx.Debug("DeviceEKStorage#getCache: unable to get generation from key: %s", key)
   322  				continue
   323  			}
   324  			deviceEK, err := s.get(mctx, generation)
   325  			switch err.(type) {
   326  			case nil, libkb.UnboxError:
   327  				s.cache[generation] = deviceEKCacheItem{
   328  					DeviceEK: deviceEK,
   329  					Err:      err,
   330  				}
   331  			default:
   332  				return nil, err
   333  			}
   334  		}
   335  		s.indexed = true
   336  	}
   337  	return s.cache, nil
   338  }
   339  
   340  func (s *DeviceEKStorage) ClearCache() {
   341  	s.Lock()
   342  	defer s.Unlock()
   343  	s.clearCache()
   344  }
   345  
   346  func (s *DeviceEKStorage) clearCache() {
   347  	s.cache = make(deviceEKCache)
   348  	s.indexed = false
   349  }
   350  
   351  func (s *DeviceEKStorage) GetAll(mctx libkb.MetaContext) (deviceEKs DeviceEKMap, err error) {
   352  	defer mctx.Trace("DeviceEKStorage#GetAll", &err)()
   353  
   354  	s.Lock()
   355  	defer s.Unlock()
   356  
   357  	cache, err := s.getCache(mctx)
   358  	if err != nil {
   359  		return nil, err
   360  	}
   361  	deviceEKs = make(DeviceEKMap)
   362  	for gen, cacheItem := range cache {
   363  		if cacheItem.Err != nil {
   364  			continue
   365  		}
   366  		deviceEKs[gen] = cacheItem.DeviceEK
   367  	}
   368  	return deviceEKs, nil
   369  }
   370  
   371  func (s *DeviceEKStorage) GetAllActive(mctx libkb.MetaContext, merkleRoot libkb.MerkleRoot) (metadatas []keybase1.DeviceEkMetadata, err error) {
   372  	defer mctx.Trace("GetAllActive", &err)()
   373  
   374  	s.Lock()
   375  	defer s.Unlock()
   376  
   377  	cache, err := s.getCache(mctx)
   378  	if err != nil {
   379  		return nil, err
   380  	}
   381  
   382  	activeKeysInOrder := []keybase1.DeviceEkMetadata{}
   383  	for _, cacheItem := range cache {
   384  		if cacheItem.Err != nil {
   385  			continue
   386  		}
   387  		deviceEK := cacheItem.DeviceEK
   388  		// Skip expired keys. Expired keys are spared from deletion past for a
   389  		// window past their expiry date, in case they're needed for
   390  		// decryption, but they're never signed over or used for encryption.
   391  		if ctimeIsStale(deviceEK.Metadata.Ctime.Time(), merkleRoot) {
   392  			continue
   393  		}
   394  		// Collect out of order, then sort below.
   395  		activeKeysInOrder = append(activeKeysInOrder, deviceEK.Metadata)
   396  	}
   397  	sort.Slice(activeKeysInOrder, func(a, b int) bool { return activeKeysInOrder[a].Generation < activeKeysInOrder[b].Generation })
   398  
   399  	return activeKeysInOrder, nil
   400  }
   401  
   402  // ListAllForUser lists the internal storage name of deviceEKs of the logged in
   403  // user. This is used for logsend purposes to debug ek state.
   404  func (s *DeviceEKStorage) ListAllForUser(mctx libkb.MetaContext) (all []string, err error) {
   405  	defer mctx.Trace("DeviceEKStorage#ListAllForUser", &err)()
   406  
   407  	s.Lock()
   408  	defer s.Unlock()
   409  
   410  	return s.listAllForUser(mctx, mctx.ActiveDevice().Username(mctx))
   411  }
   412  
   413  func (s *DeviceEKStorage) listAllForUser(mctx libkb.MetaContext, username libkb.NormalizedUsername) (all []string, err error) {
   414  	// key in the sense of a key-value pair, not a crypto key!
   415  	keys, err := s.storage.AllKeys(mctx, deviceEKSuffix)
   416  	if err != nil {
   417  		return nil, err
   418  	}
   419  	prefix := s.keyPrefixFromUsername(username)
   420  	for _, key := range keys {
   421  		if strings.HasPrefix(key, prefix) {
   422  			all = append(all, key)
   423  		}
   424  	}
   425  	return all, nil
   426  }
   427  
   428  func (s *DeviceEKStorage) MaxGeneration(mctx libkb.MetaContext, includeErrs bool) (maxGeneration keybase1.EkGeneration, err error) {
   429  	defer mctx.Trace("DeviceEKStorage#MaxGeneration", &err)()
   430  
   431  	s.Lock()
   432  	defer s.Unlock()
   433  
   434  	maxGeneration = -1
   435  	cache, err := s.getCache(mctx)
   436  	if err != nil {
   437  		return maxGeneration, err
   438  	}
   439  	for generation, cacheItem := range cache {
   440  		if cacheItem.Err != nil && !includeErrs {
   441  			continue
   442  		}
   443  		if generation > maxGeneration {
   444  			maxGeneration = generation
   445  		}
   446  	}
   447  	return maxGeneration, nil
   448  }
   449  
   450  func (s *DeviceEKStorage) DeleteExpired(mctx libkb.MetaContext, merkleRoot libkb.MerkleRoot) (expired []keybase1.EkGeneration, err error) {
   451  	defer mctx.Trace("DeviceEKStorage#DeleteExpired", &err)()
   452  
   453  	s.Lock()
   454  	defer s.Unlock()
   455  
   456  	cache, err := s.getCache(mctx)
   457  	if err != nil {
   458  		return nil, err
   459  	}
   460  
   461  	// Fall back to the device's local time if we don't have a merkle root so
   462  	// we can complete deletions offline.
   463  	var now time.Time
   464  	if merkleRoot.IsNil() {
   465  		now = time.Now()
   466  	} else {
   467  		now = keybase1.TimeFromSeconds(merkleRoot.Ctime()).Time()
   468  	}
   469  
   470  	keyMap := make(keyExpiryMap)
   471  	// We delete expired and invalid cache entries but only return the expired.
   472  	for generation, cacheItem := range cache {
   473  		if cacheItem.Err != nil {
   474  			continue
   475  		} else {
   476  			deviceEK := cacheItem.DeviceEK
   477  			var ctime keybase1.Time
   478  			// If we have a nil root _and_ a valid DeviceCtime, use that. If we're
   479  			// missing a DeviceCtime it's better to use the slightly off
   480  			// merkleCtime than a 0
   481  			if merkleRoot.IsNil() && deviceEK.Metadata.DeviceCtime > 0 {
   482  				ctime = deviceEK.Metadata.DeviceCtime
   483  			} else {
   484  				ctime = deviceEK.Metadata.Ctime
   485  			}
   486  			keyMap[generation] = ctime
   487  		}
   488  	}
   489  
   490  	expired = s.getExpiredGenerations(mctx, keyMap, now)
   491  	epick := libkb.FirstErrorPicker{}
   492  	for _, generation := range expired {
   493  		epick.Push(s.delete(mctx, generation, "generation expired"))
   494  	}
   495  
   496  	epick.Push(s.deletedWrongEldestSeqno(mctx))
   497  	return expired, epick.Error()
   498  }
   499  
   500  // getExpiredGenerations calculates which keys have expired and are safe to
   501  // delete. Keys normally expire after `libkb.MaxEphemeralContentLifetime`
   502  // unless there has been a gap in their generation. If there has been a gap of
   503  // more than a day (the normal generation time), a key can be re-used for up to
   504  // `libkb.MaxEphemeralKeyStaleness` until it is considered expired. To
   505  // determine expiration, we look at all of the current keys and account for any
   506  // gaps since we don't want to expire a key if it is still used to encrypt a
   507  // different key or ephemeral content. With deviceEKs we also have to account
   508  // for a deviceEK being created out of lock step with a userEK. Consider the
   509  // following scenario:
   510  //
   511  // At t=0, deviceA creates deviceEK_A_1 and userEK_1. At t=0.5, deviceB creates
   512  // devicekEK_B_1. At t=1, deviceEK_A_2 and userEK_2 are created and at t=1.5
   513  // deviceEK_B_2 is created. deviceEK_B_1 cannot be deleted until userEK_2 is
   514  // expired, or deviceB will delete it's deviceEK early. Since userEK_3 has not
   515  // yet been created, we may have to keep deviceEK_B_1 around until userEK_2 is
   516  // stale, at which time no more teamEKs will be encrypted by it. To account for
   517  // this (without having to interact with the userEK level via server
   518  // assistance) we extend the lifetime of deviceEK_B_1 to expire
   519  // `libkb.MaxEphemeralContentLifetime` after the creation of deviceEK_B_3, with
   520  // a maximum window of `libkb.MaxEphemeralKeyStaleness`. This is correct
   521  // because userEK_3 *must* be created at or before deviceEK_B_3's creation.
   522  func (s *DeviceEKStorage) getExpiredGenerations(mctx libkb.MetaContext, keyMap keyExpiryMap, now time.Time) (expired []keybase1.EkGeneration) {
   523  	// Sort the generations we have so we can walk through them in order.
   524  	var keys []keybase1.EkGeneration
   525  	for k := range keyMap {
   526  		keys = append(keys, k)
   527  	}
   528  	sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
   529  
   530  	for i, generation := range keys {
   531  		keyCtime := keyMap[generation].Time()
   532  
   533  		// Offset between the current key and the generation after it. Allowed
   534  		// to be at most libkb.MaxEphemeralKeyStaleness
   535  		expiryOffset1 := libkb.MaxEphemeralKeyStaleness
   536  		if i < len(keys)-1 {
   537  			expiryOffset1 = keyMap[keys[i+1]].Time().Sub(keyCtime)
   538  			// Offset can be max libkb.MaxEphemeralKeyStaleness
   539  			if expiryOffset1 > libkb.MaxEphemeralKeyStaleness {
   540  				expiryOffset1 = libkb.MaxEphemeralKeyStaleness
   541  			}
   542  		}
   543  
   544  		// Offset between the key one generation older and two generations
   545  		// older than the current key. Allowed to be at most
   546  		// libkb.MaxEphemeralKeyStaleness
   547  		expiryOffset2 := libkb.MaxEphemeralKeyStaleness
   548  		if i < len(keys)-2 {
   549  			expiryOffset2 = keyMap[keys[i+2]].Time().Sub(keyMap[keys[i+1]].Time())
   550  			if expiryOffset2 > libkb.MaxEphemeralKeyStaleness {
   551  				expiryOffset2 = libkb.MaxEphemeralKeyStaleness
   552  			}
   553  		}
   554  
   555  		expiryOffset := expiryOffset1 + expiryOffset2
   556  		if now.Sub(keyCtime) >= (libkb.MinEphemeralKeyLifetime + expiryOffset) {
   557  			s.ekLogf(mctx, "getExpiredGenerations: expired generation:%v, now: %v, keyCtime:%v, expiryOffset:%v, keyMap: %v, i:%v",
   558  				generation, now, keyCtime, expiryOffset, keyMap, i)
   559  			expired = append(expired, generation)
   560  		}
   561  	}
   562  	return expired
   563  }
   564  
   565  func (s *DeviceEKStorage) deletedWrongEldestSeqno(mctx libkb.MetaContext) (err error) {
   566  	keys, err := s.storage.AllKeys(mctx, deviceEKSuffix)
   567  	if err != nil {
   568  		return err
   569  	}
   570  	uv, err := mctx.G().GetMeUV(mctx.Ctx())
   571  	if err != nil {
   572  		return err
   573  	}
   574  	epick := libkb.FirstErrorPicker{}
   575  	for _, key := range keys {
   576  		eldestSeqno := s.keyToEldestSeqno(mctx, key)
   577  		if eldestSeqno < 0 {
   578  			continue
   579  		}
   580  		if eldestSeqno != uv.EldestSeqno {
   581  			s.ekLogf(mctx, "DeviceEKStorage#deletedWrongEldestSeqno: key: %v, uv: %v", key, uv)
   582  			epick.Push(s.storage.Erase(mctx, key))
   583  		}
   584  	}
   585  	return epick.Error()
   586  }
   587  
   588  func (s *DeviceEKStorage) ForceDeleteAll(mctx libkb.MetaContext, username libkb.NormalizedUsername) (err error) {
   589  	defer s.ekLogCTrace(mctx, "DeviceEKStorage#ForceDeleteAll", &err)()
   590  
   591  	s.Lock()
   592  	defer s.Unlock()
   593  
   594  	// only delete if the key is owned by the current user
   595  	keys, err := s.listAllForUser(mctx, username)
   596  	if err != nil {
   597  		return err
   598  	}
   599  	epick := libkb.FirstErrorPicker{}
   600  	for _, key := range keys {
   601  		s.ekLogf(mctx, "DeviceEKStorage#ForceDeleteAll: key: %v", key)
   602  		epick.Push(s.storage.Erase(mctx, key))
   603  	}
   604  
   605  	s.clearCache()
   606  	return epick.Error()
   607  }