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

     1  package ephemeral
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"sync"
     7  	"time"
     8  
     9  	lru "github.com/hashicorp/golang-lru"
    10  	"github.com/keybase/client/go/libkb"
    11  	"github.com/keybase/client/go/protocol/gregor1"
    12  	"github.com/keybase/client/go/protocol/keybase1"
    13  	"github.com/keybase/client/go/teambot"
    14  	"github.com/keybase/client/go/teams"
    15  	"github.com/keybase/clockwork"
    16  )
    17  
    18  const SkipKeygenNilMerkleRoot = "Skipping key generation, unable to fetch merkle root"
    19  
    20  // Maximum number of retries for key generation
    21  const maxRetries = 5
    22  const LibCacheEntryLifetime = time.Minute * 5
    23  const lruSize = 200
    24  
    25  type EKLib struct {
    26  	// map teamID||ekType -> latest ekGeneration so we know which teamEK to
    27  	// fetch from storage.
    28  	teamEKGenCache *lru.Cache
    29  	// map teamID||botUID||generation -> TeambotEkMetdata so non-bot members
    30  	// can know which teambot eks have been published and store their metadata
    31  	// after deriving the teamkey.
    32  	teambotEKMetadataCache *lru.Cache
    33  	sync.Mutex
    34  	stateMu sync.Mutex
    35  	locktab *libkb.LockTable
    36  
    37  	// During testing we may want to stall background work to assert cache
    38  	// state.
    39  	clock                    clockwork.Clock
    40  	backgroundCreationTestCh chan bool
    41  	backgroundDeletionTestCh chan bool
    42  	stopCh                   chan<- struct{}
    43  }
    44  
    45  var _ libkb.EKLib = (*EKLib)(nil)
    46  
    47  func NewEKLib(mctx libkb.MetaContext) *EKLib {
    48  	nlru, err := lru.New(lruSize)
    49  	if err != nil {
    50  		// lru.New only panics if size <= 0
    51  		log.Panicf("Could not create lru cache: %v", err)
    52  	}
    53  	nlru2, err := lru.New(lruSize)
    54  	if err != nil {
    55  		// lru.New only panics if size <= 0
    56  		log.Panicf("Could not create lru cache: %v", err)
    57  	}
    58  	stopCh := make(chan struct{})
    59  	ekLib := &EKLib{
    60  		teamEKGenCache:         nlru,
    61  		teambotEKMetadataCache: nlru2,
    62  		locktab:                libkb.NewLockTable(),
    63  		clock:                  clockwork.NewRealClock(),
    64  		stopCh:                 stopCh,
    65  	}
    66  	if !mctx.G().GetEnv().GetDisableEKBackgroundKeygen() {
    67  		go ekLib.backgroundKeygen(mctx, stopCh)
    68  	}
    69  	return ekLib
    70  }
    71  
    72  func (e *EKLib) lockKey(teamID keybase1.TeamID) string {
    73  	return teamID.String()
    74  }
    75  
    76  func (e *EKLib) Shutdown(mctx libkb.MetaContext) error {
    77  	e.stateMu.Lock()
    78  	defer e.stateMu.Unlock()
    79  	if e.stopCh != nil {
    80  		mctx.Debug("stopping background eklib loop")
    81  		close(e.stopCh)
    82  		e.stopCh = nil
    83  	}
    84  	e.purgeDeviceEKsIfOneshot(mctx)
    85  	return nil
    86  }
    87  
    88  func (e *EKLib) backgroundKeygen(mctx libkb.MetaContext, stopCh <-chan struct{}) {
    89  	mctx = mctx.WithLogTag("EKBKG")
    90  	mctx.Debug("backgroundKeygen: starting up")
    91  	keygenInterval := time.Hour
    92  	lastRun := time.Now()
    93  
    94  	runIfNeeded := func(force bool) {
    95  		now := libkb.ForceWallClock(time.Now())
    96  		shouldRun := now.Sub(lastRun) >= keygenInterval
    97  		mctx.Debug("backgroundKeygen: runIfNeeded: lastRun: %v, now: %v, shouldRun: %v, force: %v",
    98  			lastRun, now, shouldRun, force)
    99  		if force || shouldRun {
   100  			if err := e.KeygenIfNeeded(mctx); err != nil {
   101  				mctx.Debug("backgroundKeygen keygenIfNeeded error: %v", err)
   102  			}
   103  			lastRun = time.Now()
   104  		}
   105  	}
   106  
   107  	// Fire off on startup
   108  	runIfNeeded(true /* force */)
   109  
   110  	ticker := libkb.NewBgTicker(keygenInterval)
   111  	state := keybase1.MobileAppState_FOREGROUND
   112  	// Run every hour but also check if enough wall clock time has elapsed when
   113  	// we are in a BACKGROUNDACTIVE state.
   114  	for {
   115  		select {
   116  		case <-ticker.C:
   117  			runIfNeeded(false /* force */)
   118  		case state = <-mctx.G().MobileAppState.NextUpdate(&state):
   119  			if state == keybase1.MobileAppState_BACKGROUNDACTIVE {
   120  				// Before running  we pause briefly so we don't stampede for
   121  				// resources with other background tasks. libkb.BgTicker
   122  				// handles this internally, so we only need to throttle on
   123  				// MobileAppState change.
   124  				time.Sleep(libkb.RandomJitter(time.Second))
   125  				runIfNeeded(false /* force */)
   126  			}
   127  		case <-stopCh:
   128  			ticker.Stop()
   129  			return
   130  		}
   131  	}
   132  }
   133  
   134  func (e *EKLib) SetClock(clock clockwork.Clock) {
   135  	e.clock = clock
   136  }
   137  
   138  func (e *EKLib) setBackgroundCreationTestCh(ch chan bool) {
   139  	e.backgroundCreationTestCh = ch
   140  }
   141  
   142  func (e *EKLib) setBackgroundDeleteTestCh(ch chan bool) {
   143  	e.backgroundDeletionTestCh = ch
   144  }
   145  
   146  func (e *EKLib) KeygenIfNeeded(mctx libkb.MetaContext) (err error) {
   147  	e.Lock()
   148  	defer e.Unlock()
   149  	var merkleRoot libkb.MerkleRoot
   150  	// Always try to delete keys if we are logged in even if we get an error
   151  	// when checking our PUK or fetching the merkleRoot. `keygenIfNeeded` this
   152  	// also tries best effort to delete with errors, but try here in case we
   153  	// error before reaching that call.
   154  	defer func() {
   155  		if err != nil {
   156  			e.cleanupStaleUserAndDeviceEKsInBackground(mctx, merkleRoot)
   157  		}
   158  	}()
   159  
   160  	for tries := 0; tries < maxRetries; tries++ {
   161  		mctx.Debug("keygenIfNeeded attempt #%d: %v", tries, err)
   162  		merkleRootPtr, err := mctx.G().GetMerkleClient().FetchRootFromServer(mctx, libkb.EphemeralKeyMerkleFreshness)
   163  		if err != nil {
   164  			mctx.Debug("Unable to fetch merkle root: %v, attempting keygenIfNeeded with nil root", err)
   165  			merkleRootPtr = &libkb.MerkleRoot{}
   166  		}
   167  		if err = e.keygenIfNeededLocked(mctx, *merkleRootPtr, true /* shouldCleanup */); err == nil {
   168  			return nil
   169  		}
   170  
   171  		if !libkb.IsEphemeralRetryableError(err) {
   172  			return err
   173  		}
   174  
   175  		switch err.(type) {
   176  		case libkb.LoginRequiredError:
   177  			return err
   178  		default:
   179  			// retry
   180  		}
   181  
   182  		select {
   183  		case <-mctx.Ctx().Done():
   184  			return mctx.Ctx().Err()
   185  		case <-time.After(20 * time.Millisecond):
   186  		}
   187  	}
   188  	return err
   189  }
   190  
   191  func (e *EKLib) keygenIfNeeded(mctx libkb.MetaContext, merkleRoot libkb.MerkleRoot, shouldCleanup bool) (err error) {
   192  	defer mctx.Trace("keygenIfNeeded", &err)()
   193  	e.Lock()
   194  	defer e.Unlock()
   195  	return e.keygenIfNeededLocked(mctx, merkleRoot, shouldCleanup)
   196  }
   197  
   198  func (e *EKLib) keygenIfNeededLocked(mctx libkb.MetaContext, merkleRoot libkb.MerkleRoot, shouldCleanup bool) (err error) {
   199  	defer func() {
   200  		if shouldCleanup {
   201  			e.cleanupStaleUserAndDeviceEKsInBackground(mctx, merkleRoot)
   202  		}
   203  	}()
   204  
   205  	// Abort. We only care about calling `cleanupStaleUserAndDeviceEKs.
   206  	if merkleRoot.IsNil() {
   207  		return fmt.Errorf(SkipKeygenNilMerkleRoot)
   208  	}
   209  
   210  	if deviceEKNeeded, err := e.newDeviceEKNeeded(mctx, merkleRoot); err != nil {
   211  		return err
   212  	} else if deviceEKNeeded {
   213  		_, err = publishNewDeviceEK(mctx, merkleRoot)
   214  		if err != nil {
   215  			return err
   216  		}
   217  	}
   218  
   219  	// newUserEKNeeded checks that the current userEKStatement is signed by our
   220  	// latest PUK, is accessible to a deviceEK we have access to and that the
   221  	// key is not expired. It's crucial that this verifies that the latest PUK
   222  	// was used since we don't want to use a key signed by an old PUK for
   223  	// encryption.
   224  	if userEKNeeded, err := e.newUserEKNeeded(mctx, merkleRoot); err != nil {
   225  		return err
   226  	} else if userEKNeeded {
   227  		_, err = publishNewUserEK(mctx, merkleRoot)
   228  		if err != nil {
   229  			return err
   230  		}
   231  	}
   232  	return nil
   233  }
   234  
   235  func (e *EKLib) CleanupStaleUserAndDeviceEKs(mctx libkb.MetaContext) (err error) {
   236  	merkleRootPtr, err := mctx.G().GetMerkleClient().FetchRootFromServer(mctx, libkb.EphemeralKeyMerkleFreshness)
   237  	if err != nil {
   238  		mctx.Debug("Unable to fetch merkle root: %v, attempting deviceEK deletion with nil root", err)
   239  		merkleRootPtr = &libkb.MerkleRoot{}
   240  	}
   241  	return e.cleanupStaleUserAndDeviceEKs(mctx, *merkleRootPtr)
   242  }
   243  
   244  func (e *EKLib) cleanupStaleUserAndDeviceEKs(mctx libkb.MetaContext, merkleRoot libkb.MerkleRoot) (err error) {
   245  	defer mctx.Trace("cleanupStaleUserAndDeviceEKs", &err)()
   246  
   247  	epick := libkb.FirstErrorPicker{}
   248  
   249  	deviceEKStorage := mctx.G().GetDeviceEKStorage()
   250  	_, err = deviceEKStorage.DeleteExpired(mctx, merkleRoot)
   251  	epick.Push(err)
   252  
   253  	// Abort. We only cared about deleting expired deviceEKs.
   254  	if merkleRoot.IsNil() {
   255  		return fmt.Errorf("skipping userEK deletion, unable to fetch merkle root")
   256  	}
   257  
   258  	userEKBoxStorage := mctx.G().GetUserEKBoxStorage()
   259  	_, err = userEKBoxStorage.DeleteExpired(mctx, merkleRoot)
   260  	epick.Push(err)
   261  	return epick.Error()
   262  }
   263  
   264  func (e *EKLib) cleanupStaleUserAndDeviceEKsInBackground(mctx libkb.MetaContext, merkleRoot libkb.MerkleRoot) {
   265  	go func() {
   266  		if err := e.cleanupStaleUserAndDeviceEKs(mctx, merkleRoot); err != nil {
   267  			mctx.Debug("Unable to cleanupStaleUserAndDeviceEKsInBackground: %v", err)
   268  		}
   269  
   270  		if e.backgroundDeletionTestCh != nil {
   271  			e.backgroundDeletionTestCh <- true
   272  		}
   273  	}()
   274  }
   275  
   276  func (e *EKLib) NewDeviceEKNeeded(mctx libkb.MetaContext) (needed bool, err error) {
   277  	e.Lock()
   278  	defer e.Unlock()
   279  
   280  	merkleRootPtr, err := mctx.G().GetMerkleClient().FetchRootFromServer(mctx, libkb.EphemeralKeyMerkleFreshness)
   281  	if err != nil {
   282  		return false, err
   283  	}
   284  	return e.newDeviceEKNeeded(mctx, *merkleRootPtr)
   285  }
   286  
   287  func (e *EKLib) newDeviceEKNeeded(mctx libkb.MetaContext, merkleRoot libkb.MerkleRoot) (needed bool, err error) {
   288  	defer mctx.Trace("newDeviceEKNeeded", &err)()
   289  	defer func() {
   290  		if _, ok := err.(libkb.UnboxError); ok {
   291  			mctx.Debug("newDeviceEKNeeded: unable to fetch latest: %v, creating new deviceEK", err)
   292  			needed = true
   293  			err = nil
   294  		}
   295  	}()
   296  
   297  	s := mctx.G().GetDeviceEKStorage()
   298  	maxGeneration, err := s.MaxGeneration(mctx, true)
   299  	if err != nil {
   300  		return false, err
   301  	} else if maxGeneration < 0 {
   302  		return true, nil
   303  	}
   304  
   305  	ek, err := s.Get(mctx, maxGeneration)
   306  	if err != nil {
   307  		return false, err
   308  	}
   309  
   310  	// Ok we can access the ek, check lifetime.
   311  	mctx.Debug("nextDeviceEKNeeded at: %v", nextKeygenTime(ek.Metadata.Ctime.Time()))
   312  	return keygenNeeded(ek.Metadata.Ctime.Time(), merkleRoot), nil
   313  }
   314  
   315  func (e *EKLib) NewUserEKNeeded(mctx libkb.MetaContext) (needed bool, err error) {
   316  	e.Lock()
   317  	defer e.Unlock()
   318  
   319  	merkleRootPtr, err := mctx.G().GetMerkleClient().FetchRootFromServer(mctx, libkb.EphemeralKeyMerkleFreshness)
   320  	if err != nil {
   321  		return false, err
   322  	}
   323  	return e.newUserEKNeeded(mctx, *merkleRootPtr)
   324  }
   325  
   326  func (e *EKLib) newUserEKNeeded(mctx libkb.MetaContext, merkleRoot libkb.MerkleRoot) (needed bool, err error) {
   327  	defer mctx.Trace("newUserEKNeeded", &err)()
   328  
   329  	// Let's see what the latest server statement is. This verifies that the
   330  	// latest statement was signed by the latest PUK and otherwise fails with
   331  	// wrongKID set.
   332  	statement, _, wrongKID, err := fetchUserEKStatement(mctx, mctx.G().Env.GetUID())
   333  	if wrongKID {
   334  		return true, nil
   335  	} else if err != nil {
   336  		return false, err
   337  	}
   338  	if statement == nil {
   339  		return true, nil
   340  	}
   341  	// Can we access this generation? If not, let's regenerate.
   342  	s := mctx.G().GetUserEKBoxStorage()
   343  	ek, err := s.Get(mctx, statement.CurrentUserEkMetadata.Generation, nil)
   344  	if err != nil {
   345  		switch err.(type) {
   346  		case EphemeralKeyError:
   347  			mctx.Debug(err.Error())
   348  			return true, nil
   349  		default:
   350  			return false, err
   351  		}
   352  	}
   353  	// Ok we can access the ek, check lifetime.
   354  	mctx.Debug("nextUserEKNeeded at: %v", nextKeygenTime(ek.Metadata.Ctime.Time()))
   355  	return keygenNeeded(ek.Metadata.Ctime.Time(), merkleRoot), nil
   356  }
   357  
   358  func (e *EKLib) NewTeamEKNeeded(mctx libkb.MetaContext, teamID keybase1.TeamID) (needed bool, err error) {
   359  	lock := e.locktab.AcquireOnName(mctx.Ctx(), mctx.G(), e.lockKey(teamID))
   360  	defer lock.Release(mctx.Ctx())
   361  
   362  	merkleRootPtr, err := mctx.G().GetMerkleClient().FetchRootFromServer(mctx, libkb.EphemeralKeyMerkleFreshness)
   363  	if err != nil {
   364  		return false, err
   365  	}
   366  	needed, _, _, err = e.newTeamEKNeeded(mctx, teamID, *merkleRootPtr)
   367  	return needed, err
   368  }
   369  
   370  func (e *EKLib) newTeamEKNeeded(mctx libkb.MetaContext, teamID keybase1.TeamID,
   371  	merkleRoot libkb.MerkleRoot) (needed, backgroundGenPossible bool, latestGeneration keybase1.EkGeneration, err error) {
   372  	defer mctx.Trace("newTeamEKNeeded", &err)()
   373  
   374  	// Let's see what the latest server statement is. This verifies that the
   375  	// latest statement was signed by the latest PTK and otherwise fails with
   376  	// wrongKID set.
   377  	statement, latestGeneration, wrongKID, err := fetchTeamEKStatement(mctx, teamID)
   378  	if wrongKID {
   379  		return true, false, latestGeneration, nil
   380  	} else if err != nil {
   381  		return false, false, latestGeneration, err
   382  	}
   383  
   384  	// Let's see what the latest server statement is.
   385  	// No statement, so we need a teamEK
   386  	if statement == nil {
   387  		return true, false, latestGeneration, nil
   388  	}
   389  	// Can we access this generation? If not, let's regenerate.
   390  	s := mctx.G().GetTeamEKBoxStorage()
   391  	ek, err := s.Get(mctx, teamID, statement.CurrentTeamEkMetadata.Generation, nil)
   392  	if err != nil {
   393  		switch err.(type) {
   394  		case EphemeralKeyError:
   395  			mctx.Debug(err.Error())
   396  			return true, false, latestGeneration, nil
   397  		default:
   398  			return false, false, latestGeneration, err
   399  		}
   400  	}
   401  	// Ok we can access the ek, check lifetime.
   402  	ctime := ek.Ctime().Time()
   403  	mctx.Debug("nextTeamEKNeeded at: %v", nextKeygenTime(ctime))
   404  	if backgroundKeygenPossible(ctime, merkleRoot) {
   405  		return false, true, latestGeneration, nil
   406  	}
   407  	return keygenNeeded(ctime, merkleRoot), false, latestGeneration, nil
   408  }
   409  
   410  type teamEKGenCacheEntry struct {
   411  	Generation         keybase1.EkGeneration
   412  	Ctime              keybase1.Time
   413  	CreationInProgress bool
   414  }
   415  
   416  func (e *EKLib) newCacheEntry(generation keybase1.EkGeneration, creationInProgress bool) *teamEKGenCacheEntry {
   417  	return &teamEKGenCacheEntry{
   418  		Generation:         generation,
   419  		Ctime:              keybase1.ToTime(e.clock.Now()),
   420  		CreationInProgress: creationInProgress,
   421  	}
   422  }
   423  
   424  func (e *EKLib) cacheKey(teamID keybase1.TeamID, typ keybase1.TeamEphemeralKeyType) string {
   425  	return fmt.Sprintf("%s-%s", teamID, typ)
   426  }
   427  
   428  func (e *EKLib) teambotCacheKey(teamID keybase1.TeamID, botUID keybase1.UID, generation keybase1.EkGeneration) string {
   429  	return fmt.Sprintf("%s-%s-%d", teamID, botUID, generation)
   430  }
   431  
   432  func (e *EKLib) isEntryExpired(val interface{}) (*teamEKGenCacheEntry, bool) {
   433  	cacheEntry, ok := val.(*teamEKGenCacheEntry)
   434  	if !ok || cacheEntry == nil {
   435  		return nil, false
   436  	}
   437  	return cacheEntry, e.clock.Now().Sub(cacheEntry.Ctime.Time()) >= LibCacheEntryLifetime
   438  }
   439  
   440  func (e *EKLib) getStorageForType(mctx libkb.MetaContext, typ keybase1.TeamEphemeralKeyType) (libkb.TeamEKBoxStorage, error) {
   441  	switch typ {
   442  	case keybase1.TeamEphemeralKeyType_TEAM:
   443  		return mctx.G().GetTeamEKBoxStorage(), nil
   444  	case keybase1.TeamEphemeralKeyType_TEAMBOT:
   445  		return mctx.G().GetTeambotEKBoxStorage(), nil
   446  	default:
   447  		return nil, fmt.Errorf("Unknown key type %v", typ)
   448  	}
   449  }
   450  
   451  func (e *EKLib) PurgeTeamEKCachesForTeamID(mctx libkb.MetaContext, teamID keybase1.TeamID) {
   452  	e.purgeCachesForTeamIDAndType(mctx, teamID, keybase1.TeamEphemeralKeyType_TEAM)
   453  }
   454  
   455  func (e *EKLib) PurgeTeambotEKCachesForTeamID(mctx libkb.MetaContext, teamID keybase1.TeamID) {
   456  	e.purgeCachesForTeamIDAndType(mctx, teamID, keybase1.TeamEphemeralKeyType_TEAMBOT)
   457  }
   458  
   459  func (e *EKLib) purgeCachesForTeamIDAndType(mctx libkb.MetaContext, teamID keybase1.TeamID, typ keybase1.TeamEphemeralKeyType) {
   460  	mctx.Debug("purgeCachesForTeamIDAndType: teamID: %v, typ: %v", teamID, typ)
   461  	e.teamEKGenCache.Remove(e.cacheKey(teamID, typ))
   462  	storage, err := e.getStorageForType(mctx, typ)
   463  	if err != nil {
   464  		mctx.Debug("unable to purgeCachesForTeamIDAndType: %v", err)
   465  		return
   466  	}
   467  	if err := storage.PurgeCacheForTeamID(mctx, teamID); err != nil {
   468  		mctx.Debug("unable to purgeCachesForTeamIDAndType: %v", err)
   469  	}
   470  }
   471  
   472  func (e *EKLib) PurgeTeamEKCachesForTeamIDAndGeneration(mctx libkb.MetaContext, teamID keybase1.TeamID, generation keybase1.EkGeneration) {
   473  	e.purgeCachesForTeamIDAndTypeByGeneration(mctx, teamID, generation, keybase1.TeamEphemeralKeyType_TEAM)
   474  }
   475  
   476  func (e *EKLib) PurgeTeambotEKCachesForTeamIDAndGeneration(mctx libkb.MetaContext, teamID keybase1.TeamID, generation keybase1.EkGeneration) {
   477  	e.purgeCachesForTeamIDAndTypeByGeneration(mctx, teamID, generation, keybase1.TeamEphemeralKeyType_TEAMBOT)
   478  
   479  }
   480  
   481  func (e *EKLib) PurgeAllTeambotMetadataCaches(mctx libkb.MetaContext) {
   482  	mctx.Debug("PurgeAllTeambotMetadataCaches")
   483  	e.teambotEKMetadataCache.Purge()
   484  }
   485  
   486  func (e *EKLib) PurgeTeambotMetadataCache(mctx libkb.MetaContext, teamID keybase1.TeamID,
   487  	botUID keybase1.UID, generation keybase1.EkGeneration) {
   488  	mctx.Debug("PurgeTeambotMetadataCache: teamID: %v, botUID: %v generation: %v",
   489  		teamID, botUID, generation)
   490  	cacheKey := e.teambotCacheKey(teamID, botUID, generation)
   491  	e.teambotEKMetadataCache.Remove(cacheKey)
   492  }
   493  
   494  func (e *EKLib) purgeCachesForTeamIDAndTypeByGeneration(mctx libkb.MetaContext, teamID keybase1.TeamID,
   495  	generation keybase1.EkGeneration, typ keybase1.TeamEphemeralKeyType) {
   496  	mctx.Debug("purgeCachesForTeamIDAndTypeByGeneration: teamID: %v, typ: %v generation: %v", teamID, typ, generation)
   497  	cacheKey := e.cacheKey(teamID, typ)
   498  	val, ok := e.teamEKGenCache.Get(cacheKey)
   499  	if ok {
   500  		if cacheEntry, _ := e.isEntryExpired(val); cacheEntry != nil && cacheEntry.Generation != generation {
   501  			e.teamEKGenCache.Remove(cacheKey)
   502  		}
   503  	}
   504  	storage, err := e.getStorageForType(mctx, typ)
   505  	if err != nil {
   506  		mctx.Debug("unable to purgeCachesForTeamIDAndType: %v", err)
   507  		return
   508  	}
   509  	if err := storage.Delete(mctx, teamID, generation); err != nil {
   510  		mctx.Debug("unable to purgeCachesForTeamIDAndTypeByGeneration: %v", err)
   511  	}
   512  }
   513  
   514  func (e *EKLib) GetOrCreateLatestTeamEK(mctx libkb.MetaContext, teamID keybase1.TeamID) (
   515  	ek keybase1.TeamEphemeralKey, created bool, err error) {
   516  	mctx = mctx.WithLogTag("GOCTEK")
   517  
   518  	err = teamEKRetryWrapper(mctx, func() error {
   519  		lock := e.locktab.AcquireOnName(mctx.Ctx(), mctx.G(), e.lockKey(teamID))
   520  		defer lock.Release(mctx.Ctx())
   521  		ek, created, err = e.getOrCreateLatestTeamEKLocked(mctx, teamID, nil)
   522  		if err != nil {
   523  			return err
   524  		}
   525  		return err
   526  	})
   527  	if err != nil {
   528  		return ek, false, err
   529  	}
   530  	// sanity check key type
   531  	typ, err := ek.KeyType()
   532  	if err != nil {
   533  		return ek, false, err
   534  	} else if !typ.IsTeam() {
   535  		return ek, false, NewIncorrectTeamEphemeralKeyTypeError(typ, keybase1.TeamEphemeralKeyType_TEAM)
   536  	}
   537  	return ek, created, err
   538  }
   539  
   540  func (e *EKLib) getOrCreateLatestTeamEKLocked(mctx libkb.MetaContext, teamID keybase1.TeamID, forceCreateGen *keybase1.EkGeneration) (
   541  	ek keybase1.TeamEphemeralKey, created bool, err error) {
   542  	defer mctx.Trace("getOrCreateLatestTeamEKLocked", &err)()
   543  
   544  	teamEKBoxStorage := mctx.G().GetTeamEKBoxStorage()
   545  
   546  	// Check if we have a cached latest generation
   547  	cacheKey := e.cacheKey(teamID, keybase1.TeamEphemeralKeyType_TEAM)
   548  	val, ok := e.teamEKGenCache.Get(cacheKey)
   549  	if ok {
   550  		if cacheEntry, expired := e.isEntryExpired(val); !expired || cacheEntry.CreationInProgress {
   551  			ek, err = teamEKBoxStorage.Get(mctx, teamID, cacheEntry.Generation, nil)
   552  			if err == nil {
   553  				return ek, false, nil
   554  			}
   555  			mctx.Debug("unable to get teamEK, attempting regen: %v", err)
   556  			// kill our cached entry and possibly re-generate below
   557  			e.teamEKGenCache.Remove(cacheKey)
   558  		}
   559  	}
   560  
   561  	merkleRootPtr, err := mctx.G().GetMerkleClient().FetchRootFromServer(mctx, libkb.EphemeralKeyMerkleFreshness)
   562  	if err != nil {
   563  		return ek, false, err
   564  	}
   565  	merkleRoot := *merkleRootPtr
   566  	defer func() { e.cleanupStaleUserAndDeviceEKsInBackground(mctx, merkleRoot) }()
   567  	defer func() {
   568  		if _, err := teamEKBoxStorage.DeleteExpired(mctx, teamID, merkleRoot); err != nil {
   569  			mctx.Debug("Unable to DeleteExpired: %v", err)
   570  		}
   571  	}()
   572  
   573  	// First publish new device or userEKs if we need to. We pass shouldCleanup
   574  	// = false so we can run deletion in the background ourselves and not block
   575  	// this call.
   576  	if err = e.keygenIfNeeded(mctx, merkleRoot, false /* shouldCleanup */); err != nil {
   577  		return ek, false, err
   578  	}
   579  
   580  	// newTeamEKNeeded checks that the current teamEKStatement is signed by the
   581  	// latest PTK, is accessible to a userEK we have access to and that the key
   582  	// is not expired. It's crucial that this verifies that the latest PTK was
   583  	// used since we don't want to use a key signed by an old PTK for
   584  	// encryption.
   585  	teamEKNeeded, backgroundGenPossible, latestGeneration, err := e.newTeamEKNeeded(mctx, teamID, merkleRoot)
   586  	switch {
   587  	case err != nil:
   588  		return ek, false, err
   589  	case backgroundGenPossible:
   590  		// Our current teamEK is *almost* expired but otherwise valid, so let's
   591  		// create the new teamEK in the background. For large teams and an
   592  		// empty UPAK cache it can be expensive to do this calculation and it's
   593  		// unfortunate to block message sending while we otherwise have access
   594  		// to a working teamEK.
   595  		go func() {
   596  			if e.backgroundCreationTestCh != nil {
   597  				<-e.backgroundCreationTestCh
   598  			}
   599  
   600  			publishedMetadata, err := publishNewTeamEK(mctx, teamID, merkleRoot, nil)
   601  			// Grab the lock once we finish publishing so we do don't block
   602  			lock := e.locktab.AcquireOnName(mctx.Ctx(), mctx.G(), e.lockKey(teamID))
   603  			defer lock.Release(mctx.Ctx())
   604  			created := false
   605  			if err != nil {
   606  				// Let's just clear the cache and try again later
   607  				mctx.Debug("Unable to getOrCreateLatestTeamEKLocked in the background: %v", err)
   608  				e.teamEKGenCache.Remove(cacheKey)
   609  			} else {
   610  				e.teamEKGenCache.Add(cacheKey, e.newCacheEntry(
   611  					publishedMetadata.Generation, false))
   612  				created = true
   613  			}
   614  
   615  			if e.backgroundCreationTestCh != nil {
   616  				e.backgroundCreationTestCh <- created
   617  			}
   618  		}()
   619  	case teamEKNeeded:
   620  		publishedMetadata, err := publishNewTeamEK(mctx, teamID, merkleRoot, nil)
   621  		if err != nil {
   622  			return ek, false, err
   623  		}
   624  		latestGeneration = publishedMetadata.Generation
   625  	case forceCreateGen != nil && latestGeneration == *forceCreateGen:
   626  		// Teambot creation can request a new teamEK be force published. We
   627  		// only want to do this once so we make sure no on else has published
   628  		// before us and incremented the generation.
   629  		publishedMetadata, err := publishNewTeamEK(mctx, teamID, merkleRoot, forceCreateGen)
   630  		if err != nil {
   631  			return ek, false, err
   632  		}
   633  		latestGeneration = publishedMetadata.Generation
   634  	}
   635  
   636  	ek, err = teamEKBoxStorage.Get(mctx, teamID, latestGeneration, nil)
   637  	if err != nil {
   638  		return ek, false, err
   639  	}
   640  	// Cache the latest generation and signal future callers if we are trying
   641  	// to create the new key in the background.
   642  	e.teamEKGenCache.Add(cacheKey, e.newCacheEntry(latestGeneration, backgroundGenPossible))
   643  	return ek, teamEKNeeded, nil
   644  }
   645  
   646  // GetTeamEK fetches the TeamEK for the given `generation`. If this fails and the
   647  // `generation` is also the current maxGeneration, create a new teamEK.
   648  func (e *EKLib) GetTeamEK(mctx libkb.MetaContext, teamID keybase1.TeamID, generation keybase1.EkGeneration,
   649  	contentCtime *gregor1.Time) (ek keybase1.TeamEphemeralKey, err error) {
   650  	mctx = mctx.WithLogTag("GTEK")
   651  	defer mctx.Trace("GetTeamEK", &err)()
   652  
   653  	teamEKBoxStorage := mctx.G().GetTeamEKBoxStorage()
   654  	ek, err = teamEKBoxStorage.Get(mctx, teamID, generation, contentCtime)
   655  	if err != nil {
   656  		if _, ok := err.(EphemeralKeyError); ok {
   657  			mctx.Debug(err.Error())
   658  			// If we are unable to get the current max generation, try to kick
   659  			// off creation of a new key.
   660  			go func(mctx libkb.MetaContext) {
   661  				maxGeneration, err := teamEKBoxStorage.MaxGeneration(mctx, teamID, true)
   662  				if err != nil {
   663  					mctx.Debug("Unable to get MaxGeneration: %v", err)
   664  					return
   665  				}
   666  				if generation == maxGeneration {
   667  					_, created, cerr := e.GetOrCreateLatestTeamEK(mctx, teamID)
   668  					if cerr != nil {
   669  						mctx.Debug("Unable to GetOrCreateLatestTeamEK: %v", cerr)
   670  					}
   671  					if e.backgroundCreationTestCh != nil {
   672  						e.backgroundCreationTestCh <- created
   673  					}
   674  				}
   675  			}(libkb.NewMetaContextBackground(mctx.G()))
   676  		}
   677  		return ek, err
   678  	}
   679  	// sanity check key type
   680  	typ, err := ek.KeyType()
   681  	if err != nil {
   682  		return ek, err
   683  	} else if !typ.IsTeam() {
   684  		return ek, NewIncorrectTeamEphemeralKeyTypeError(typ, keybase1.TeamEphemeralKeyType_TEAM)
   685  	}
   686  	return ek, err
   687  }
   688  
   689  // GetOrCreateLatestTeambotEK handles two separate cases based on the `botUID`
   690  // parameter. If `botUID == currentUID`, we are a bot member and thus can
   691  // *only* get the latest known key, we do not have the ability to create new
   692  // ones. Since bot members do not have access to the per-team-key, they must
   693  // depend on team members who do to derive and publish a new key.
   694  func (e *EKLib) GetOrCreateLatestTeambotEK(mctx libkb.MetaContext, teamID keybase1.TeamID, gBotUID gregor1.UID) (
   695  	ek keybase1.TeamEphemeralKey, created bool, err error) {
   696  	mctx = mctx.WithLogTag("GOCLTBEK")
   697  	botUID, err := keybase1.UIDFromSlice(gBotUID.Bytes())
   698  	if err != nil {
   699  		return ek, false, err
   700  	}
   701  
   702  	// We are the bot, try to access our latest key
   703  	if teambot.CurrentUserIsBot(mctx, &gBotUID) {
   704  		created = false
   705  		ek, err = e.getLatestTeambotEK(mctx, teamID, botUID)
   706  		switch err := err.(type) {
   707  		case nil:
   708  		case EphemeralKeyError:
   709  			// Make sure we have a valid deviceEK, we may be in a oneshot
   710  			// configuration and be fighting with another bot for one.
   711  			if err2 := e.KeygenIfNeeded(mctx); err2 != nil {
   712  				return ek, false, err2
   713  			}
   714  			// Ping team members to generate the latest key for us
   715  			if err2 := teambot.NotifyTeambotEKNeeded(mctx, teamID, 0); err2 != nil {
   716  				mctx.Debug("Unable to NotifyTeambotEKNeeded %v", err2)
   717  			}
   718  			// See if we should downgrade this to a transient error. Since
   719  			// bot members get a key when added to the team this should
   720  			// only happen in a tight race before the key is created or if
   721  			// the TeamEK has been purged and we don't have a new one.
   722  			if err.AllowTransient() {
   723  				err = newTransientEphemeralKeyError(err)
   724  			}
   725  			return ek, false, err
   726  		default:
   727  			return ek, false, err
   728  		}
   729  	} else { // we are a team member who needs the latest bot key, get or create that puppy.
   730  		err = teamEKRetryWrapper(mctx, func() error {
   731  			lock := e.locktab.AcquireOnName(mctx.Ctx(), mctx.G(), e.lockKey(teamID))
   732  			defer lock.Release(mctx.Ctx())
   733  			ek, created, err = e.getOrCreateLatestTeambotEKLocked(mctx, teamID, botUID, nil)
   734  			return err
   735  		})
   736  		if err != nil {
   737  			return ek, false, err
   738  		}
   739  	}
   740  
   741  	// sanity check key type
   742  	typ, err := ek.KeyType()
   743  	if err != nil {
   744  		return ek, false, err
   745  	} else if !typ.IsTeambot() {
   746  		return ek, false, NewIncorrectTeamEphemeralKeyTypeError(typ, keybase1.TeamEphemeralKeyType_TEAMBOT)
   747  	}
   748  	return ek, created, err
   749  }
   750  
   751  func (e *EKLib) ForceCreateTeambotEK(mctx libkb.MetaContext, teamID keybase1.TeamID, gBotUID gregor1.UID,
   752  	forceCreateGen keybase1.EkGeneration) (ek keybase1.TeamEphemeralKey, created bool, err error) {
   753  	mctx = mctx.WithLogTag("FCTEK")
   754  	botUID, err := keybase1.UIDFromSlice(gBotUID.Bytes())
   755  	if err != nil {
   756  		return ek, false, err
   757  	}
   758  
   759  	// We are the bot, try to access our latest key
   760  	if teambot.CurrentUserIsBot(mctx, &gBotUID) {
   761  		return ek, false, fmt.Errorf("Cannot force create as a bot member")
   762  	}
   763  	err = teamEKRetryWrapper(mctx, func() error {
   764  		lock := e.locktab.AcquireOnName(mctx.Ctx(), mctx.G(), e.lockKey(teamID))
   765  		defer lock.Release(mctx.Ctx())
   766  		ek, created, err = e.getOrCreateLatestTeambotEKLocked(mctx, teamID, botUID, &forceCreateGen)
   767  		return err
   768  	})
   769  	if err != nil {
   770  		return ek, false, err
   771  	}
   772  
   773  	// sanity check key type
   774  	typ, err := ek.KeyType()
   775  	if err != nil {
   776  		return ek, false, err
   777  	} else if !typ.IsTeambot() {
   778  		return ek, false, NewIncorrectTeamEphemeralKeyTypeError(typ, keybase1.TeamEphemeralKeyType_TEAMBOT)
   779  	}
   780  	return ek, created, err
   781  }
   782  
   783  func (e *EKLib) getOrCreateLatestTeambotEKLocked(mctx libkb.MetaContext, teamID keybase1.TeamID,
   784  	botUID keybase1.UID, forceCreateGen *keybase1.EkGeneration) (ek keybase1.TeamEphemeralKey, created bool, err error) {
   785  	defer mctx.Trace("getOrCreateLatestTeambotEKLocked", &err)()
   786  
   787  	// first check if we have the teamEK cached, in which case we can just
   788  	// derive the teambotEK and return that.
   789  	cacheKey := e.cacheKey(teamID, keybase1.TeamEphemeralKeyType_TEAM)
   790  	val, ok := e.teamEKGenCache.Get(cacheKey)
   791  	if ok {
   792  		if cacheEntry, expired := e.isEntryExpired(val); !expired || cacheEntry.CreationInProgress {
   793  			teamEK, err := mctx.G().GetTeamEKBoxStorage().Get(mctx, teamID, cacheEntry.Generation, nil)
   794  			if err == nil {
   795  				return e.deriveAndMaybePublishTeambotEK(mctx, teamID, teamEK, botUID)
   796  			}
   797  			mctx.Debug("unable to get teamEK, attempting regen: %v", err)
   798  			// kill our cached entry and possibly re-generate below
   799  			e.teamEKGenCache.Remove(cacheKey)
   800  		}
   801  	}
   802  
   803  	// get the latest teamEK to derive the latest teambotEK
   804  	teamEK, _, err := e.getOrCreateLatestTeamEKLocked(mctx, teamID, forceCreateGen)
   805  	if err != nil {
   806  		return ek, false, err
   807  	}
   808  	return e.deriveAndMaybePublishTeambotEK(mctx, teamID, teamEK, botUID)
   809  }
   810  
   811  func (e *EKLib) deriveAndMaybePublishTeambotEK(mctx libkb.MetaContext, teamID keybase1.TeamID,
   812  	teamEK keybase1.TeamEphemeralKey, botUID keybase1.UID) (ek keybase1.TeamEphemeralKey, created bool, err error) {
   813  
   814  	// sanity check the teamEK is of type TEAM
   815  	typ, err := teamEK.KeyType()
   816  	if err != nil {
   817  		return ek, false, err
   818  	} else if !typ.IsTeam() {
   819  		return ek, false, NewIncorrectTeamEphemeralKeyTypeError(typ, keybase1.TeamEphemeralKeyType_TEAM)
   820  	}
   821  
   822  	seed := deriveTeambotEKFromTeamEK(mctx, teamEK.Team(), botUID)
   823  
   824  	// Check our teambotEK cache and see if we should attempt to publish the
   825  	// our derived key or not.
   826  	cacheKey := e.teambotCacheKey(teamID, botUID, teamEK.Generation())
   827  	val, ok := e.teambotEKMetadataCache.Get(cacheKey)
   828  	if ok {
   829  		metadata, ok := val.(keybase1.TeambotEkMetadata)
   830  		if ok {
   831  			ek = keybase1.NewTeamEphemeralKeyWithTeambot(keybase1.TeambotEk{
   832  				Seed:     keybase1.Bytes32(seed),
   833  				Metadata: metadata,
   834  			})
   835  			return ek, false, nil
   836  		}
   837  	}
   838  
   839  	merkleRootPtr, err := mctx.G().GetMerkleClient().FetchRootFromServer(mctx, libkb.EphemeralKeyMerkleFreshness)
   840  	if err != nil {
   841  		return ek, false, err
   842  	}
   843  	merkleRoot := *merkleRootPtr
   844  
   845  	metadata := keybase1.TeambotEkMetadata{
   846  		Kid:        seed.DeriveDHKey().GetKID(),
   847  		Generation: teamEK.Team().Metadata.Generation,
   848  		Uid:        botUID,
   849  		HashMeta:   merkleRoot.HashMeta(),
   850  		// The ctime is derivable from the hash meta, by fetching the hashed
   851  		// root from the server, but including it saves readers a potential
   852  		// extra round trip.
   853  		Ctime: keybase1.TimeFromSeconds(merkleRoot.Ctime()),
   854  	}
   855  
   856  	team, err := teams.Load(mctx.Ctx(), mctx.G(), keybase1.LoadTeamArg{
   857  		ID: teamID,
   858  	})
   859  	if err != nil {
   860  		return ek, false, err
   861  	}
   862  
   863  	upak, _, err := mctx.G().GetUPAKLoader().LoadV2(
   864  		libkb.NewLoadUserArgWithMetaContext(mctx).WithUID(botUID))
   865  	if err != nil {
   866  		return ek, false, err
   867  	}
   868  	role, err := team.MemberRole(mctx.Ctx(), upak.ToUserVersion())
   869  	if err != nil {
   870  		return ek, false, err
   871  	}
   872  
   873  	// If the bot is not a restricted bot member don't try to publish the key
   874  	// for them. This can happen when decrypting past content after the bot is
   875  	// removed from the team.
   876  	if role.IsRestrictedBot() {
   877  		sig, box, err := prepareNewTeambotEK(mctx, team, botUID, seed, &metadata, merkleRoot)
   878  		if err != nil {
   879  			return ek, false, err
   880  		}
   881  		if box != nil {
   882  			if err = postNewTeambotEK(mctx, team.ID, sig, box.Box); err != nil {
   883  				return ek, false, err
   884  			}
   885  		}
   886  	}
   887  
   888  	e.teambotEKMetadataCache.Add(cacheKey, metadata)
   889  	ek = keybase1.NewTeamEphemeralKeyWithTeambot(keybase1.TeambotEk{
   890  		Seed:     keybase1.Bytes32(seed),
   891  		Metadata: metadata,
   892  	})
   893  
   894  	return ek, role.IsRestrictedBot(), nil
   895  }
   896  
   897  func (e *EKLib) getLatestTeambotEK(mctx libkb.MetaContext, teamID keybase1.TeamID,
   898  	botUID keybase1.UID) (ek keybase1.TeamEphemeralKey, err error) {
   899  	defer mctx.Trace("getLatestTeambotEK", &err)()
   900  	lock := e.locktab.AcquireOnName(mctx.Ctx(), mctx.G(), e.lockKey(teamID))
   901  	defer lock.Release(mctx.Ctx())
   902  
   903  	storage := mctx.G().GetTeambotEKBoxStorage()
   904  	// Check if we have a cached latest generation
   905  	cacheKey := e.cacheKey(teamID, keybase1.TeamEphemeralKeyType_TEAMBOT)
   906  	val, ok := e.teamEKGenCache.Get(cacheKey)
   907  	if ok {
   908  		if cacheEntry, expired := e.isEntryExpired(val); !expired {
   909  			return storage.Get(mctx, teamID, cacheEntry.Generation, nil)
   910  		}
   911  		// kill our cached entry and possibly re-generate below
   912  		e.teamEKGenCache.Remove(cacheKey)
   913  	}
   914  
   915  	merkleRootPtr, err := mctx.G().GetMerkleClient().FetchRootFromServer(mctx, libkb.EphemeralKeyMerkleFreshness)
   916  	if err != nil {
   917  		return ek, err
   918  	}
   919  	merkleRoot := *merkleRootPtr
   920  	defer func() {
   921  		if _, err := storage.DeleteExpired(mctx, teamID, merkleRoot); err != nil {
   922  			mctx.Debug("Unable to DeleteExpired: %v", err)
   923  		}
   924  	}()
   925  
   926  	// Let's see what the latest teambot ek is. This verifies that the metadata
   927  	// was signed by the latest PTK and otherwise fails with wrongKID set.
   928  	metadata, wrongKID, err := fetchLatestTeambotEK(mctx, teamID)
   929  	switch {
   930  	case metadata == nil:
   931  		err = newEKMissingBoxErr(mctx, TeambotEKKind, -1)
   932  		return ek, err
   933  	case wrongKID:
   934  		now := keybase1.ToTime(e.clock.Now())
   935  		permitted, ctime, err := teambot.TeambotEKWrongKIDPermitted(mctx, teamID, botUID,
   936  			metadata.Generation, now)
   937  		if err != nil {
   938  			return ek, err
   939  		}
   940  		mctx.Debug("getLatestTeambotEK: wrongKID set, permitted: %v, ctime: %v",
   941  			permitted, ctime)
   942  		if !permitted {
   943  			return ek, newTeambotEKWrongKIDErr(mctx, ctime, now)
   944  		}
   945  
   946  		// Ping other team members to create the new key for us.
   947  		if err = teambot.NotifyTeambotEKNeeded(mctx, teamID, 0); err != nil {
   948  			// Charge forward here, we'll try again next time we fetch this
   949  			// key.
   950  			mctx.Debug("Unable to NotifyTeambotEKNeeded %v", err)
   951  		}
   952  	case err != nil:
   953  		return ek, err
   954  	}
   955  
   956  	ek, err = storage.Get(mctx, teamID, metadata.Generation, nil)
   957  	if err != nil {
   958  		return ek, err
   959  	}
   960  	e.teamEKGenCache.Add(cacheKey, e.newCacheEntry(ek.Generation(), false))
   961  	return ek, nil
   962  }
   963  
   964  // GetTeambotEK fetches the TeambotEK for the given `generation`. If `gBotUID`
   965  // is the current UID we fetch the boxed teambotEK if it exists.  Otherwise we
   966  // derived the key from the teamEK at the given `generation`.
   967  func (e *EKLib) GetTeambotEK(mctx libkb.MetaContext, teamID keybase1.TeamID, gBotUID gregor1.UID,
   968  	generation keybase1.EkGeneration, contentCtime *gregor1.Time) (ek keybase1.TeamEphemeralKey, err error) {
   969  	mctx = mctx.WithLogTag("GTBEK")
   970  	defer mctx.Trace("GetTeambotEK", &err)()
   971  
   972  	botUID, err := keybase1.UIDFromSlice(gBotUID.Bytes())
   973  	if err != nil {
   974  		return ek, err
   975  	}
   976  	// We are the bot, try to access the key
   977  	if teambot.CurrentUserIsBot(mctx, &gBotUID) {
   978  		ek, err = mctx.G().GetTeambotEKBoxStorage().Get(mctx, teamID, generation, contentCtime)
   979  		if err != nil {
   980  			if _, ok := err.(EphemeralKeyError); ok {
   981  				// If we don't have access to the max generation, request
   982  				// access to this key. We may not have access to earlier keys
   983  				// and don't want to spam out requests for new ones.
   984  				maxGeneration, err2 := mctx.G().GetTeambotEKBoxStorage().MaxGeneration(mctx, teamID, true)
   985  				if err2 != nil {
   986  					mctx.Debug("Unable to get MaxGeneration: %v", err)
   987  					return ek, err
   988  				}
   989  				if generation == maxGeneration {
   990  					// Ping team members to generate the latest key for us
   991  					if err2 = teambot.NotifyTeambotEKNeeded(mctx, teamID, 0); err2 != nil {
   992  						mctx.Debug("Unable to NotifyTeambotEKNeeded %v", err2)
   993  					}
   994  				}
   995  				// NOTE we don't downgrade this error to transient since the
   996  				// bot may have added a device after the EK was generated, and
   997  				// will never get access to it.
   998  			}
   999  			return ek, err
  1000  		}
  1001  	} else {
  1002  		teamEK, err := e.GetTeamEK(mctx, teamID, generation, contentCtime)
  1003  		if err != nil {
  1004  			return ek, err
  1005  		}
  1006  		ek, _, err = e.deriveAndMaybePublishTeambotEK(mctx, teamID, teamEK, botUID)
  1007  		if err != nil {
  1008  			return ek, err
  1009  		}
  1010  	}
  1011  
  1012  	// Sanity check key type
  1013  	typ, err := ek.KeyType()
  1014  	if err != nil {
  1015  		return ek, err
  1016  	} else if !typ.IsTeambot() {
  1017  		return ek, NewIncorrectTeamEphemeralKeyTypeError(typ, keybase1.TeamEphemeralKeyType_TEAMBOT)
  1018  	}
  1019  	return ek, err
  1020  }
  1021  
  1022  func (e *EKLib) NewEphemeralSeed() (seed keybase1.Bytes32, err error) {
  1023  	return makeNewRandomSeed()
  1024  }
  1025  
  1026  func (e *EKLib) DeriveDeviceDHKey(seed keybase1.Bytes32) *libkb.NaclDHKeyPair {
  1027  	deviceEKSeed := DeviceEKSeed(seed)
  1028  	return deviceEKSeed.DeriveDHKey()
  1029  }
  1030  
  1031  func (e *EKLib) SignedDeviceEKStatementFromSeed(mctx libkb.MetaContext, generation keybase1.EkGeneration,
  1032  	seed keybase1.Bytes32, signingKey libkb.GenericKey) (statement keybase1.DeviceEkStatement, signedStatement string, err error) {
  1033  	defer mctx.Trace("SignedDeviceEKStatementFromSeed", &err)()
  1034  
  1035  	merkleRootPtr, err := mctx.G().GetMerkleClient().FetchRootFromServer(mctx, libkb.EphemeralKeyMerkleFreshness)
  1036  	if err != nil {
  1037  		return statement, signedStatement, err
  1038  	}
  1039  	dhKeypair := e.DeriveDeviceDHKey(seed)
  1040  	return signDeviceEKStatement(generation, dhKeypair, signingKey, *merkleRootPtr)
  1041  }
  1042  
  1043  // For device provisioning
  1044  func (e *EKLib) BoxLatestUserEK(mctx libkb.MetaContext, receiverKey libkb.NaclDHKeyPair,
  1045  	deviceEKGeneration keybase1.EkGeneration) (userEKBox *keybase1.UserEkBoxed, err error) {
  1046  	defer mctx.Trace("BoxLatestUserEK", &err)()
  1047  
  1048  	// Let's make sure we are up to date with keys first and we have the latest userEK cached.
  1049  	if err = e.KeygenIfNeeded(mctx); err != nil {
  1050  		return nil, err
  1051  	}
  1052  
  1053  	userEKBoxStorage := mctx.G().GetUserEKBoxStorage()
  1054  	maxGeneration, err := userEKBoxStorage.MaxGeneration(mctx, false)
  1055  	if err != nil {
  1056  		return nil, err
  1057  	}
  1058  	if maxGeneration < 0 {
  1059  		mctx.Debug("No userEK found")
  1060  		return nil, nil
  1061  	}
  1062  	userEK, err := userEKBoxStorage.Get(mctx, maxGeneration, nil)
  1063  	if err != nil {
  1064  		return nil, err
  1065  	}
  1066  	box, err := receiverKey.EncryptToString(userEK.Seed[:], nil)
  1067  	if err != nil {
  1068  		return nil, err
  1069  	}
  1070  	return &keybase1.UserEkBoxed{
  1071  		Box:                box,
  1072  		DeviceEkGeneration: deviceEKGeneration,
  1073  		Metadata:           userEK.Metadata,
  1074  	}, nil
  1075  }
  1076  
  1077  func (e *EKLib) PrepareNewUserEK(mctx libkb.MetaContext, merkleRoot libkb.MerkleRoot,
  1078  	pukSeed libkb.PerUserKeySeed) (sig string, boxes []keybase1.UserEkBoxMetadata,
  1079  	newMetadata keybase1.UserEkMetadata, myBox *keybase1.UserEkBoxed, err error) {
  1080  	signingKey, err := pukSeed.DeriveSigningKey()
  1081  	if err != nil {
  1082  		return "", nil, newMetadata, nil, err
  1083  	}
  1084  	return prepareNewUserEK(mctx, merkleRoot, signingKey)
  1085  }
  1086  
  1087  func (e *EKLib) BoxLatestTeamEK(mctx libkb.MetaContext, teamID keybase1.TeamID, recipients []keybase1.UID) (teamEKBoxes *[]keybase1.TeamEkBoxMetadata, err error) {
  1088  	defer mctx.Trace("BoxLatestTeamEK", &err)()
  1089  
  1090  	// If we need a new teamEK let's just create it when needed, the new
  1091  	// members will be part of the team and will have access to it via the
  1092  	// normal mechanisms.
  1093  	if teamEKNeeded, err := e.NewTeamEKNeeded(mctx, teamID); err != nil {
  1094  		return nil, err
  1095  	} else if teamEKNeeded {
  1096  		return nil, nil
  1097  	}
  1098  
  1099  	lock := e.locktab.AcquireOnName(mctx.Ctx(), mctx.G(), e.lockKey(teamID))
  1100  	defer lock.Release(mctx.Ctx())
  1101  
  1102  	merkleRootPtr, err := mctx.G().GetMerkleClient().FetchRootFromServer(mctx, libkb.EphemeralKeyMerkleFreshness)
  1103  	if err != nil {
  1104  		return nil, err
  1105  	}
  1106  	statementMap, err := fetchUserEKStatements(mctx, recipients)
  1107  	if err != nil {
  1108  		return nil, err
  1109  	}
  1110  	usersMetadata, err := activeUserEKMetadata(mctx, statementMap, *merkleRootPtr)
  1111  	if err != nil {
  1112  		return nil, err
  1113  	}
  1114  
  1115  	teamEKBoxStorage := mctx.G().GetTeamEKBoxStorage()
  1116  	maxGeneration, err := teamEKBoxStorage.MaxGeneration(mctx, teamID, false)
  1117  	if err != nil {
  1118  		return nil, err
  1119  	}
  1120  	ek, err := teamEKBoxStorage.Get(mctx, teamID, maxGeneration, nil)
  1121  	if err != nil {
  1122  		return nil, err
  1123  	}
  1124  	typ, err := ek.KeyType()
  1125  	if err != nil {
  1126  		return nil, err
  1127  	} else if !typ.IsTeam() {
  1128  		return nil, NewIncorrectTeamEphemeralKeyTypeError(typ, keybase1.TeamEphemeralKeyType_TEAM)
  1129  	}
  1130  	teamEK := ek.Team()
  1131  	boxes, _, err := boxTeamEKForUsers(mctx, usersMetadata, teamEK)
  1132  	return boxes, err
  1133  }
  1134  
  1135  func (e *EKLib) PrepareNewTeamEK(mctx libkb.MetaContext, teamID keybase1.TeamID, signingKey libkb.NaclSigningKeyPair,
  1136  	recipients []keybase1.UID) (sig string, boxes *[]keybase1.TeamEkBoxMetadata, newMetadata keybase1.TeamEkMetadata, myBox *keybase1.TeamEkBoxed, err error) {
  1137  
  1138  	// If we need a new teamEK let's just create it when needed, the new
  1139  	// members will be part of the team and will have access to it via the
  1140  	// normal mechanisms.
  1141  	if teamEKNeeded, err := e.NewTeamEKNeeded(mctx, teamID); err != nil {
  1142  		return "", nil, newMetadata, nil, err
  1143  	} else if teamEKNeeded {
  1144  		return "", nil, newMetadata, nil, nil
  1145  	}
  1146  
  1147  	lock := e.locktab.AcquireOnName(mctx.Ctx(), mctx.G(), e.lockKey(teamID))
  1148  	defer lock.Release(mctx.Ctx())
  1149  
  1150  	merkleRootPtr, err := mctx.G().GetMerkleClient().FetchRootFromServer(mctx, libkb.EphemeralKeyMerkleFreshness)
  1151  	if err != nil {
  1152  		return "", nil, newMetadata, nil, err
  1153  	}
  1154  	merkleRoot := *merkleRootPtr
  1155  
  1156  	statementMap, err := fetchUserEKStatements(mctx, recipients)
  1157  	if err != nil {
  1158  		return "", nil, newMetadata, nil, err
  1159  	}
  1160  	usersMetadata, err := activeUserEKMetadata(mctx, statementMap, merkleRoot)
  1161  	if err != nil {
  1162  		return "", nil, newMetadata, nil, err
  1163  	}
  1164  	return prepareNewTeamEK(mctx, teamID, signingKey, usersMetadata, merkleRoot)
  1165  }
  1166  
  1167  func (e *EKLib) ClearCaches(mctx libkb.MetaContext) {
  1168  	defer mctx.Trace("EKLib.ClearCaches", nil)()
  1169  	mctx.Debug("| EKLib.ClearCaches teamEKGenCache")
  1170  	e.teamEKGenCache.Purge()
  1171  	e.teambotEKMetadataCache.Purge()
  1172  	mctx.Debug("| EKLib.ClearCaches deviceEKStorage")
  1173  	if s := mctx.G().GetDeviceEKStorage(); s != nil {
  1174  		s.ClearCache()
  1175  	}
  1176  	mctx.Debug("| EKLib.ClearCaches userEKBoxStorage")
  1177  	if s := mctx.G().GetUserEKBoxStorage(); s != nil {
  1178  		s.ClearCache()
  1179  	}
  1180  	mctx.Debug("| EKLib.ClearCaches teamEKBoxStorage")
  1181  	if s := mctx.G().GetTeamEKBoxStorage(); s != nil {
  1182  		s.ClearCache()
  1183  	}
  1184  	mctx.Debug("| EKLib.ClearCaches teambotEKBoxStorage")
  1185  	if s := mctx.G().GetTeambotEKBoxStorage(); s != nil {
  1186  		s.ClearCache()
  1187  	}
  1188  }
  1189  
  1190  func (e *EKLib) purgeDeviceEKsIfOneshot(mctx libkb.MetaContext) {
  1191  	if deviceEKStorage := mctx.G().GetDeviceEKStorage(); deviceEKStorage != nil {
  1192  		if isOneshot, err := mctx.G().IsOneshot(mctx.Ctx()); err != nil {
  1193  			mctx.Debug("unable to check IsOneshot %v", err)
  1194  		} else if isOneshot {
  1195  			username := mctx.G().Env.GetUsername()
  1196  			mctx.Debug("Calling ForceDeleteAll because %q is running in oneshot mode", username)
  1197  			if err := deviceEKStorage.ForceDeleteAll(mctx, username); err != nil {
  1198  				mctx.Debug("Unable to complete ForceDeleteAll: %v", err)
  1199  			}
  1200  		}
  1201  	}
  1202  }
  1203  
  1204  func (e *EKLib) OnLogin(mctx libkb.MetaContext) error {
  1205  	keygen := func() {
  1206  		if err := e.KeygenIfNeeded(mctx); err != nil {
  1207  			mctx.Debug("OnLogin error: %v", err)
  1208  		}
  1209  	}
  1210  	if mctx.G().Standalone {
  1211  		// If we are in standalone run this synchronously to avoid racing if we
  1212  		// are attempting logout.
  1213  		keygen()
  1214  	} else {
  1215  		go keygen()
  1216  	}
  1217  	if deviceEKStorage := mctx.G().GetDeviceEKStorage(); deviceEKStorage != nil {
  1218  		deviceEKStorage.SetLogPrefix(mctx)
  1219  	}
  1220  	return nil
  1221  }
  1222  
  1223  func (e *EKLib) OnLogout(mctx libkb.MetaContext) error {
  1224  	e.ClearCaches(mctx)
  1225  	if deviceEKStorage := mctx.G().GetDeviceEKStorage(); deviceEKStorage != nil {
  1226  		deviceEKStorage.SetLogPrefix(mctx)
  1227  	}
  1228  	e.purgeDeviceEKsIfOneshot(mctx)
  1229  	return nil
  1230  }
  1231  
  1232  func (e *EKLib) OnDbNuke(mctx libkb.MetaContext) error {
  1233  	e.ClearCaches(mctx)
  1234  	return nil
  1235  }