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 }