github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/libkbfs/key_manager.go (about) 1 // Copyright 2016 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package libkbfs 6 7 import ( 8 "github.com/keybase/client/go/kbfs/data" 9 "github.com/keybase/client/go/kbfs/kbfscrypto" 10 "github.com/keybase/client/go/kbfs/kbfsmd" 11 "github.com/keybase/client/go/kbfs/libkey" 12 "github.com/keybase/client/go/kbfs/tlf" 13 "github.com/keybase/client/go/kbfs/tlfhandle" 14 kbname "github.com/keybase/client/go/kbun" 15 "github.com/keybase/client/go/libkb" 16 "github.com/keybase/client/go/logger" 17 "github.com/keybase/client/go/protocol/keybase1" 18 "github.com/pkg/errors" 19 "golang.org/x/net/context" 20 ) 21 22 // KeyManagerStandard implements the KeyManager interface by fetching 23 // keys from KeyOps and KBPKI, and computing the complete keys 24 // necessary to run KBFS. 25 type KeyManagerStandard struct { 26 config Config 27 log logger.Logger 28 deferLog logger.Logger 29 } 30 31 // NewKeyManagerStandard returns a new KeyManagerStandard 32 func NewKeyManagerStandard(config Config) *KeyManagerStandard { 33 log := config.MakeLogger("") 34 return &KeyManagerStandard{config, log, log.CloneWithAddedDepth(1)} 35 } 36 37 // GetTLFCryptKeyForEncryption implements the KeyManager interface for 38 // KeyManagerStandard. 39 func (km *KeyManagerStandard) GetTLFCryptKeyForEncryption(ctx context.Context, 40 kmd libkey.KeyMetadata) (tlfCryptKey kbfscrypto.TLFCryptKey, err error) { 41 return km.getTLFCryptKeyUsingCurrentDevice(ctx, kmd, 42 kmd.LatestKeyGeneration(), false) 43 } 44 45 // GetTLFCryptKeyForMDDecryption implements the KeyManager interface 46 // for KeyManagerStandard. 47 func (km *KeyManagerStandard) GetTLFCryptKeyForMDDecryption( 48 ctx context.Context, kmdToDecrypt, kmdWithKeys libkey.KeyMetadata) ( 49 tlfCryptKey kbfscrypto.TLFCryptKey, err error) { 50 return km.getTLFCryptKey(ctx, kmdWithKeys, kmdToDecrypt.LatestKeyGeneration(), 51 getTLFCryptKeyAnyDevice|getTLFCryptKeyDoCache) 52 } 53 54 // GetTLFCryptKeyForBlockDecryption implements the KeyManager interface for 55 // KeyManagerStandard. 56 func (km *KeyManagerStandard) GetTLFCryptKeyForBlockDecryption( 57 ctx context.Context, kmd libkey.KeyMetadata, blockPtr data.BlockPointer) ( 58 tlfCryptKey kbfscrypto.TLFCryptKey, err error) { 59 return km.getTLFCryptKeyUsingCurrentDevice(ctx, kmd, blockPtr.KeyGen, true) 60 } 61 62 // GetFirstTLFCryptKey implements the KeyManager interface for 63 // KeyManagerStandard. 64 func (km *KeyManagerStandard) GetFirstTLFCryptKey( 65 ctx context.Context, kmd libkey.KeyMetadata) ( 66 kbfscrypto.TLFCryptKey, error) { 67 return km.getTLFCryptKey( 68 ctx, kmd, kbfsmd.FirstValidKeyGen, getTLFCryptKeyAnyDevice) 69 } 70 71 // GetTLFCryptKeyOfAllGenerations implements the KeyManager interface for 72 // KeyManagerStandard. 73 func (km *KeyManagerStandard) GetTLFCryptKeyOfAllGenerations( 74 ctx context.Context, kmd libkey.KeyMetadata) ( 75 keys []kbfscrypto.TLFCryptKey, err error) { 76 for g := kbfsmd.FirstValidKeyGen; g <= kmd.LatestKeyGeneration(); g++ { 77 var key kbfscrypto.TLFCryptKey 78 key, err = km.getTLFCryptKeyUsingCurrentDevice(ctx, kmd, g, true) 79 if err != nil { 80 return keys, err 81 } 82 keys = append(keys, key) 83 } 84 return keys, nil 85 } 86 87 func (km *KeyManagerStandard) getTLFCryptKeyUsingCurrentDevice( 88 ctx context.Context, kmd libkey.KeyMetadata, keyGen kbfsmd.KeyGen, cache bool) ( 89 tlfCryptKey kbfscrypto.TLFCryptKey, err error) { 90 flags := getTLFCryptKeyFlags(0) 91 if cache { 92 flags = getTLFCryptKeyDoCache 93 } 94 return km.getTLFCryptKey(ctx, kmd, keyGen, flags) 95 } 96 97 type getTLFCryptKeyFlags byte 98 99 const ( 100 getTLFCryptKeyAnyDevice getTLFCryptKeyFlags = 1 << iota 101 getTLFCryptKeyDoCache 102 getTLFCryptKeyPromptPaper 103 ) 104 105 func (km *KeyManagerStandard) getTLFCryptKey(ctx context.Context, 106 kmd libkey.KeyMetadata, keyGen kbfsmd.KeyGen, flags getTLFCryptKeyFlags) ( 107 kbfscrypto.TLFCryptKey, error) { 108 tlfID := kmd.TlfID() 109 110 // Classic public TLFs and public implicit teams use a dummy crypt key. 111 if kmd.TypeForKeying() == tlf.PublicKeying || tlfID.Type() == tlf.Public { 112 return kbfscrypto.PublicTLFCryptKey, nil 113 } 114 115 if keyGen < kbfsmd.FirstValidKeyGen { 116 return kbfscrypto.TLFCryptKey{}, errors.WithStack(kbfsmd.InvalidKeyGenerationError{TlfID: tlfID, KeyGen: keyGen}) 117 } 118 // Is this some key we don't know yet? Shouldn't really ever 119 // happen, but during migration there was a race that made this 120 // possible (KBFS-3774). If the key gen really doesn't exist, 121 // we'll return an InvalidKeyGenerationError below. 122 if keyGen > kmd.LatestKeyGeneration() { 123 km.log.CDebugf(ctx, "Key gen %d is bigger than latest key gen %d", 124 keyGen, kmd.LatestKeyGeneration()) 125 } 126 127 // look in the cache first 128 kcache := km.config.KeyCache() 129 tlfCryptKey, err := kcache.GetTLFCryptKey(tlfID, keyGen) 130 switch err := err.(type) { 131 case nil: 132 return tlfCryptKey, nil 133 case KeyCacheMissError: 134 break 135 default: 136 return kbfscrypto.TLFCryptKey{}, err 137 } 138 139 // Team TLF keys come from the service. 140 if kmd.TypeForKeying() == tlf.TeamKeying { 141 tid, err := kmd.GetTlfHandle().FirstResolvedWriter().AsTeam() 142 if err != nil { 143 return kbfscrypto.TLFCryptKey{}, err 144 } 145 keys, _, err := km.config.KBPKI().GetTeamTLFCryptKeys( 146 ctx, tid, keyGen, km.config.OfflineAvailabilityForID(tlfID)) 147 if err != nil { 148 return kbfscrypto.TLFCryptKey{}, err 149 } 150 tlfCryptKey, ok := keys[keyGen] 151 if !ok { 152 return kbfscrypto.TLFCryptKey{}, 153 kbfsmd.InvalidKeyGenerationError{TlfID: tlfID, KeyGen: keyGen} 154 } 155 if flags&getTLFCryptKeyDoCache != 0 { 156 if err = kcache.PutTLFCryptKey( 157 tlfID, keyGen, tlfCryptKey); err != nil { 158 return kbfscrypto.TLFCryptKey{}, err 159 } 160 } 161 162 return tlfCryptKey, nil 163 } 164 165 // Get the encrypted version of this secret key for this device 166 kbpki := km.config.KBPKI() 167 session, err := kbpki.GetCurrentSession(ctx) 168 if err != nil { 169 return kbfscrypto.TLFCryptKey{}, err 170 } 171 172 clientHalf, serverHalfID, cryptPublicKey, err := 173 km.getTLFCryptKeyParams(ctx, kmd, keyGen, session.UID, 174 session.Name, flags) 175 176 var notPerDeviceEncrypted bool 177 if _, notPerDeviceEncrypted = err.(kbfsmd.TLFCryptKeyNotPerDeviceEncrypted); notPerDeviceEncrypted { // nolint 178 // get the key we want using the current crypt key 179 currKeyGen := kmd.LatestKeyGeneration() 180 // look in the cache first 181 latestKey, err := kcache.GetTLFCryptKey(tlfID, currKeyGen) 182 switch err := err.(type) { 183 case nil: 184 case KeyCacheMissError: 185 // not cached, look up the params 186 clientHalf, serverHalfID, cryptPublicKey, err2 := 187 km.getTLFCryptKeyParams(ctx, kmd, currKeyGen, 188 session.UID, session.Name, flags) 189 if err2 != nil { 190 return kbfscrypto.TLFCryptKey{}, err2 191 } 192 // unmask it 193 latestKey, err2 = km.unmaskTLFCryptKey(ctx, serverHalfID, cryptPublicKey, clientHalf) 194 if err2 != nil { 195 return kbfscrypto.TLFCryptKey{}, err2 196 } 197 default: 198 return kbfscrypto.TLFCryptKey{}, err 199 } 200 // get the historic key we want 201 tlfCryptKey, err = 202 kmd.GetHistoricTLFCryptKey(km.config.Codec(), keyGen, latestKey) 203 if err != nil { 204 km.log.CDebugf( 205 ctx, "Can't get historic TLF crypt key for id=%s, keyGen=%d", 206 tlfID, keyGen) 207 return kbfscrypto.TLFCryptKey{}, err 208 } 209 } else if err != nil { 210 return kbfscrypto.TLFCryptKey{}, err 211 } else { 212 // unmask it 213 tlfCryptKey, err = km.unmaskTLFCryptKey(ctx, serverHalfID, cryptPublicKey, clientHalf) 214 if err != nil { 215 return kbfscrypto.TLFCryptKey{}, err 216 } 217 } 218 219 if flags&getTLFCryptKeyDoCache != 0 { 220 if err = kcache.PutTLFCryptKey(tlfID, keyGen, tlfCryptKey); err != nil { 221 return kbfscrypto.TLFCryptKey{}, err 222 } 223 } 224 225 return tlfCryptKey, nil 226 } 227 228 func (km *KeyManagerStandard) getTLFCryptKeyParams( 229 ctx context.Context, kmd libkey.KeyMetadata, 230 keyGen kbfsmd.KeyGen, uid keybase1.UID, username kbname.NormalizedUsername, 231 flags getTLFCryptKeyFlags) ( 232 clientHalf kbfscrypto.TLFCryptKeyClientHalf, 233 serverHalfID kbfscrypto.TLFCryptKeyServerHalfID, 234 cryptPublicKey kbfscrypto.CryptPublicKey, err error) { 235 kbpki := km.config.KBPKI() 236 crypto := km.config.Crypto() 237 localMakeRekeyReadError := func(err error) error { 238 return makeRekeyReadError( 239 ctx, err, kbpki, km.config, kmd, uid, username) 240 } 241 242 if flags&getTLFCryptKeyAnyDevice != 0 { 243 publicKeys, err := kbpki.GetCryptPublicKeys( 244 ctx, uid, km.config.OfflineAvailabilityForID(kmd.TlfID())) 245 if err != nil { 246 return kbfscrypto.TLFCryptKeyClientHalf{}, 247 kbfscrypto.TLFCryptKeyServerHalfID{}, 248 kbfscrypto.CryptPublicKey{}, err 249 } 250 251 keys := make([]EncryptedTLFCryptKeyClientAndEphemeral, 0, 252 len(publicKeys)) 253 serverHalfIDs := make([]kbfscrypto.TLFCryptKeyServerHalfID, 0, len(publicKeys)) 254 publicKeyLookup := make([]int, 0, len(publicKeys)) 255 256 for i, k := range publicKeys { 257 ePublicKey, encryptedClientHalf, serverHalfID, found, err := kmd.GetTLFCryptKeyParams(keyGen, uid, k) 258 if _, notPerDeviceEncrypted := err.(kbfsmd.TLFCryptKeyNotPerDeviceEncrypted); notPerDeviceEncrypted { 259 return kbfscrypto.TLFCryptKeyClientHalf{}, 260 kbfscrypto.TLFCryptKeyServerHalfID{}, 261 kbfscrypto.CryptPublicKey{}, err 262 } 263 if err != nil { 264 km.log.CDebugf(ctx, "Got error for GetTLFCryptKeyParams(%d, %v, %v); skipping: %+v", keyGen, uid, k, err) 265 continue 266 } 267 if !found { 268 km.log.CDebugf(ctx, "Could not find key info for(%d, %v, %v); skipping", keyGen, uid, k) 269 continue 270 } 271 272 serverHalfIDs = append(serverHalfIDs, serverHalfID) 273 keys = append(keys, EncryptedTLFCryptKeyClientAndEphemeral{ 274 PubKey: k, 275 ClientHalf: encryptedClientHalf, 276 EPubKey: ePublicKey, 277 }) 278 publicKeyLookup = append(publicKeyLookup, i) 279 } 280 if len(keys) == 0 { 281 err := errors.New("no valid public keys found") 282 return kbfscrypto.TLFCryptKeyClientHalf{}, 283 kbfscrypto.TLFCryptKeyServerHalfID{}, 284 kbfscrypto.CryptPublicKey{}, 285 localMakeRekeyReadError(err) 286 } 287 var index int 288 clientHalf, index, err = crypto.DecryptTLFCryptKeyClientHalfAny(ctx, 289 keys, flags&getTLFCryptKeyPromptPaper != 0) 290 cause := errors.Cause(err) 291 _, isDecryptError := cause.(libkb.DecryptionError) 292 _, isNoKeyError := cause.(libkb.NoSecretKeyError) 293 if isDecryptError || isNoKeyError { 294 km.log.CDebugf(ctx, "Got decryption error from service: %+v", err) 295 return kbfscrypto.TLFCryptKeyClientHalf{}, 296 kbfscrypto.TLFCryptKeyServerHalfID{}, 297 kbfscrypto.CryptPublicKey{}, 298 localMakeRekeyReadError(err) 299 } else if err != nil { 300 return kbfscrypto.TLFCryptKeyClientHalf{}, 301 kbfscrypto.TLFCryptKeyServerHalfID{}, 302 kbfscrypto.CryptPublicKey{}, err 303 } 304 serverHalfID = serverHalfIDs[index] 305 cryptPublicKey = publicKeys[publicKeyLookup[index]] 306 } else { 307 session, err := kbpki.GetCurrentSession(ctx) 308 if err != nil { 309 return kbfscrypto.TLFCryptKeyClientHalf{}, 310 kbfscrypto.TLFCryptKeyServerHalfID{}, 311 kbfscrypto.CryptPublicKey{}, err 312 } 313 cryptPublicKey = session.CryptPublicKey 314 315 ePublicKey, encryptedClientHalf, foundServerHalfID, found, err := 316 kmd.GetTLFCryptKeyParams(keyGen, uid, cryptPublicKey) 317 if _, notPerDeviceEncrypted := err.(kbfsmd.TLFCryptKeyNotPerDeviceEncrypted); notPerDeviceEncrypted { 318 return kbfscrypto.TLFCryptKeyClientHalf{}, 319 kbfscrypto.TLFCryptKeyServerHalfID{}, 320 kbfscrypto.CryptPublicKey{}, err 321 } 322 if err != nil { 323 return kbfscrypto.TLFCryptKeyClientHalf{}, 324 kbfscrypto.TLFCryptKeyServerHalfID{}, 325 kbfscrypto.CryptPublicKey{}, err 326 } else if !found { 327 return kbfscrypto.TLFCryptKeyClientHalf{}, 328 kbfscrypto.TLFCryptKeyServerHalfID{}, 329 kbfscrypto.CryptPublicKey{}, 330 localMakeRekeyReadError(errors.Errorf( 331 "could not find params for "+ 332 "uid=%s device key=%s", 333 uid, cryptPublicKey)) 334 } 335 336 clientHalf, err = crypto.DecryptTLFCryptKeyClientHalf( 337 ctx, ePublicKey, encryptedClientHalf) 338 if err != nil { 339 return kbfscrypto.TLFCryptKeyClientHalf{}, 340 kbfscrypto.TLFCryptKeyServerHalfID{}, 341 kbfscrypto.CryptPublicKey{}, err 342 } 343 344 serverHalfID = foundServerHalfID 345 } 346 return 347 } 348 349 func (km *KeyManagerStandard) unmaskTLFCryptKey(ctx context.Context, serverHalfID kbfscrypto.TLFCryptKeyServerHalfID, 350 cryptPublicKey kbfscrypto.CryptPublicKey, 351 clientHalf kbfscrypto.TLFCryptKeyClientHalf) ( 352 kbfscrypto.TLFCryptKey, error) { 353 // get the server-side key-half, do the unmasking, possibly cache the result, return 354 // TODO: can parallelize the get() with decryption 355 serverHalf, err := km.config.KeyOps().GetTLFCryptKeyServerHalf(ctx, serverHalfID, 356 cryptPublicKey) 357 if err != nil { 358 return kbfscrypto.TLFCryptKey{}, err 359 } 360 tlfCryptKey := kbfscrypto.UnmaskTLFCryptKey(serverHalf, clientHalf) 361 return tlfCryptKey, nil 362 } 363 364 func (km *KeyManagerStandard) updateKeyBundles(ctx context.Context, 365 md *RootMetadata, 366 updatedWriterKeys, updatedReaderKeys kbfsmd.UserDevicePublicKeys, 367 ePubKey kbfscrypto.TLFEphemeralPublicKey, 368 ePrivKey kbfscrypto.TLFEphemeralPrivateKey, 369 tlfCryptKeys []kbfscrypto.TLFCryptKey) error { 370 371 serverHalves, err := md.updateKeyBundles( 372 km.config.Codec(), updatedWriterKeys, updatedReaderKeys, 373 ePubKey, ePrivKey, tlfCryptKeys) 374 if err != nil { 375 return err 376 } 377 378 // Push new keys to the key server. 379 // 380 // TODO: Should accumulate the server halves across multiple 381 // key generations and push them all at once right before the 382 // MD push, although this only really matters for MDv2. 383 for _, serverHalvesGen := range serverHalves { 384 if err = km.config.KeyOps(). 385 PutTLFCryptKeyServerHalves(ctx, serverHalvesGen); err != nil { 386 return err 387 } 388 } 389 390 return nil 391 } 392 393 func (km *KeyManagerStandard) usersWithNewDevices(ctx context.Context, 394 tlfID tlf.ID, keys, expectedKeys kbfsmd.UserDevicePublicKeys) map[keybase1.UID]bool { 395 users := make(map[keybase1.UID]bool) 396 for u, expectedDeviceKeys := range expectedKeys { 397 deviceKeys, ok := keys[u] 398 if !ok { 399 // Currently there probably shouldn't be any new users 400 // in the handle, but don't error just in case we ever 401 // want to support that in the future. 402 km.log.CInfof(ctx, "Rekey %s: adding new user %s", tlfID, u) 403 users[u] = true 404 continue 405 } 406 for key := range expectedDeviceKeys { 407 km.log.CDebugf(ctx, "Checking key %v", key) 408 if !deviceKeys[key] { 409 km.log.CInfof(ctx, "Rekey %s: adding new device %s for user %s", 410 tlfID, key, u) 411 users[u] = true 412 break 413 } 414 } 415 } 416 return users 417 } 418 419 func (km *KeyManagerStandard) usersWithRemovedDevices(ctx context.Context, 420 tlfID tlf.ID, keys, expectedKeys kbfsmd.UserDevicePublicKeys) map[keybase1.UID]bool { 421 users := make(map[keybase1.UID]bool) 422 for u, deviceKeys := range keys { 423 expectedDeviceKeys, ok := expectedKeys[u] 424 if !ok { 425 // Currently there probably shouldn't be any users removed 426 // from the handle, but don't error just in case we ever 427 // want to support that in the future. 428 km.log.CInfof(ctx, "Rekey %s: removing user %s", tlfID, u) 429 users[u] = true 430 continue 431 } 432 for key := range deviceKeys { 433 // Make sure every kid has an expected key 434 if !expectedDeviceKeys[key] { 435 km.log.CInfof(ctx, "Rekey %s: removing device %s for user %s", 436 tlfID, key, u) 437 users[u] = true 438 break 439 } 440 } 441 } 442 return users 443 } 444 445 func (km *KeyManagerStandard) identifyUIDSets(ctx context.Context, 446 tlfID tlf.ID, writersToIdentify map[keybase1.UID]bool, 447 readersToIdentify map[keybase1.UID]bool) error { 448 ids := make([]keybase1.UserOrTeamID, 0, 449 len(writersToIdentify)+len(readersToIdentify)) 450 for u := range writersToIdentify { 451 ids = append(ids, u.AsUserOrTeam()) 452 } 453 for u := range readersToIdentify { 454 ids = append(ids, u.AsUserOrTeam()) 455 } 456 kbpki := km.config.KBPKI() 457 458 // Let the service know that we're doing the identifies because of 459 // a rekey, so they can suppress popups in some cases. 460 ctx, err := tlfhandle.MakeExtendedIdentify( 461 ctx, keybase1.TLFIdentifyBehavior_KBFS_REKEY) 462 if err != nil { 463 return err 464 } 465 466 return tlfhandle.IdentifyUserList( 467 ctx, kbpki, kbpki, ids, tlfID.Type(), 468 km.config.OfflineAvailabilityForID(tlfID)) 469 } 470 471 // generateKeyMapForUsers returns a kbfsmd.UserDevicePublicKeys object for 472 // the given list of users. Note that keyless users are retained in 473 // the returned kbfsmd.UserDevicePublicKeys object. 474 func (km *KeyManagerStandard) generateKeyMapForUsers( 475 ctx context.Context, users []keybase1.UserOrTeamID, 476 offline keybase1.OfflineAvailability) ( 477 kbfsmd.UserDevicePublicKeys, error) { 478 keyMap := make(kbfsmd.UserDevicePublicKeys) 479 480 // TODO: parallelize 481 for _, w := range users { 482 uid := w.AsUserOrBust() // only private TLFs should call this 483 // HACK: clear cache 484 km.config.KeybaseService().FlushUserFromLocalCache(ctx, uid) 485 publicKeys, err := km.config.KBPKI().GetCryptPublicKeys( 486 ctx, uid, offline) 487 if err != nil { 488 return nil, err 489 } 490 keyMap[uid] = make(kbfsmd.DevicePublicKeys) 491 for _, key := range publicKeys { 492 keyMap[uid][key] = true 493 } 494 } 495 496 return keyMap, nil 497 } 498 499 // Rekey implements the KeyManager interface for KeyManagerStandard. 500 // 501 // TODO: Make this less terrible. See KBFS-1799. 502 func (km *KeyManagerStandard) Rekey(ctx context.Context, md *RootMetadata, promptPaper bool) ( 503 mdChanged bool, cryptKey *kbfscrypto.TLFCryptKey, err error) { 504 km.log.CDebugf(ctx, "Rekey %s (prompt for paper key: %t)", 505 md.TlfID(), promptPaper) 506 defer func() { km.deferLog.CDebugf(ctx, "Rekey %s done: %+v", md.TlfID(), err) }() 507 508 if md.TypeForKeying() == tlf.TeamKeying { 509 return false, nil, errors.New( 510 "Rekeying is not done by KBFS for team TLFs") 511 } 512 513 currKeyGen := md.LatestKeyGeneration() 514 if (md.TypeForKeying() == tlf.PublicKeying) != (currKeyGen == kbfsmd.PublicKeyGen) { 515 return false, nil, errors.Errorf( 516 "ID %v has keying type=%s but currKeyGen is %d (isPublic=%t)", 517 md.TlfID(), md.TypeForKeying(), currKeyGen, 518 currKeyGen == kbfsmd.PublicKeyGen) 519 } 520 521 if promptPaper && md.TypeForKeying() != tlf.PrivateKeying { 522 return false, nil, errors.Errorf( 523 "promptPaper set for non-private TLF %v", md.TlfID()) 524 } 525 526 handle := md.GetTlfHandle() 527 528 session, err := km.config.KBPKI().GetCurrentSession(ctx) 529 if err != nil { 530 return false, nil, err 531 } 532 533 idGetter := tlfhandle.ConstIDGetter{ID: md.TlfID()} 534 resolvedHandle, err := handle.ResolveAgain( 535 ctx, km.config.KBPKI(), idGetter, km.config) 536 if err != nil { 537 return false, nil, err 538 } 539 540 isWriter := resolvedHandle.IsWriter(session.UID) 541 if md.TypeForKeying() == tlf.PrivateKeying && !isWriter { 542 // If I was already a reader, there's nothing more to do 543 if handle.IsReader(session.UID) { 544 resolvedHandle = handle 545 km.log.CDebugf(ctx, "Local user is not a writer, and was "+ 546 "already a reader; reverting back to the original handle") 547 } else { 548 // Only allow yourself to change 549 resolvedHandle, err = handle.ResolveAgainForUser( 550 ctx, km.config.KBPKI(), idGetter, km.config, session.UID) 551 if err != nil { 552 return false, nil, err 553 } 554 } 555 } 556 557 eq, err := handle.Equals(km.config.Codec(), *resolvedHandle) 558 if err != nil { 559 return false, nil, err 560 } 561 handleChanged := !eq 562 if handleChanged { 563 km.log.CDebugf(ctx, "handle for %s resolved to %s", 564 handle.GetCanonicalPath(), 565 resolvedHandle.GetCanonicalPath()) 566 567 // Check with the server to see if the handle became a conflict. 568 latestHandle, err := km.config.MDOps().GetLatestHandleForTLF(ctx, md.TlfID()) 569 if err != nil { 570 return false, nil, err 571 } 572 if latestHandle.ConflictInfo != nil { 573 km.log.CDebugf(ctx, "handle for %s is conflicted", 574 handle.GetCanonicalPath()) 575 } 576 resolvedHandle, err = resolvedHandle.WithUpdatedConflictInfo( 577 km.config.Codec(), latestHandle.ConflictInfo) 578 if err != nil { 579 return false, nil, err 580 } 581 } 582 583 // For a public or team TLF there's no rekeying to be done, but we 584 // should still update the writer list. 585 if md.TypeForKeying() != tlf.PrivateKeying { 586 if !handleChanged { 587 km.log.CDebugf(ctx, 588 "Skipping rekeying %s (%s): handle hasn't changed", 589 md.TlfID(), md.TypeForKeying()) 590 return false, nil, nil 591 } 592 return true, nil, md.updateFromTlfHandle(resolvedHandle) 593 } 594 595 // Decide whether we have a new device and/or a revoked device, or neither. 596 // Look up all the device public keys for all writers and readers first. 597 598 incKeyGen := currKeyGen < kbfsmd.FirstValidKeyGen 599 600 if !isWriter && incKeyGen { 601 // Readers cannot create the first key generation 602 return false, nil, tlfhandle.NewReadAccessError( 603 resolvedHandle, session.Name, resolvedHandle.GetCanonicalPath()) 604 } 605 606 offline := km.config.OfflineAvailabilityForID(md.TlfID()) 607 608 // All writer keys in the desired keyset 609 updatedWriterKeys, err := km.generateKeyMapForUsers( 610 ctx, resolvedHandle.ResolvedWriters(), offline) 611 if err != nil { 612 return false, nil, err 613 } 614 // All reader keys in the desired keyset 615 updatedReaderKeys, err := km.generateKeyMapForUsers( 616 ctx, resolvedHandle.ResolvedReaders(), offline) 617 if err != nil { 618 return false, nil, err 619 } 620 621 addNewReaderDevice := false 622 addNewWriterDevice := false 623 var newReaderUsers map[keybase1.UID]bool 624 var newWriterUsers map[keybase1.UID]bool 625 var readersToPromote map[keybase1.UID]bool 626 627 // Figure out if we need to add or remove any keys. 628 // If we're already incrementing the key generation then we don't need to 629 // figure out the key delta. 630 addNewReaderDeviceForSelf := false 631 if !incKeyGen { 632 // See if there is at least one new device in relation to the 633 // current key bundle 634 writers, readers, err := md.getUserDevicePublicKeys() 635 if err != nil { 636 return false, nil, err 637 } 638 639 newWriterUsers = km.usersWithNewDevices( 640 ctx, md.TlfID(), writers, updatedWriterKeys) 641 newReaderUsers = km.usersWithNewDevices( 642 ctx, md.TlfID(), readers, updatedReaderKeys) 643 addNewWriterDevice = len(newWriterUsers) > 0 644 addNewReaderDevice = len(newReaderUsers) > 0 645 646 wRemoved := km.usersWithRemovedDevices( 647 ctx, md.TlfID(), writers, updatedWriterKeys) 648 rRemoved := km.usersWithRemovedDevices( 649 ctx, md.TlfID(), readers, updatedReaderKeys) 650 651 readersToPromote = make(map[keybase1.UID]bool, len(rRemoved)) 652 653 // Before we add the removed devices, check if we are adding a 654 // new reader device for ourselves. 655 _, addNewReaderDeviceForSelf = newReaderUsers[session.UID] 656 657 for u := range rRemoved { 658 // FIXME (potential): this could cause a reader to attempt to rekey 659 // in the case of a revocation for the currently logged-in user. I 660 // _think_ incKeyGen above protects against this, but I'm not 661 // confident. 662 newReaderUsers[u] = true 663 // Track which readers have been promoted. This must happen before 664 // the following line adds all the removed writers to the writer 665 // set 666 if newWriterUsers[u] { 667 readersToPromote[u] = true 668 } 669 } 670 for u := range wRemoved { 671 newWriterUsers[u] = true 672 } 673 674 incKeyGen = len(wRemoved) > 0 || (len(rRemoved) > len(readersToPromote)) 675 676 if err := km.identifyUIDSets(ctx, md.TlfID(), newWriterUsers, newReaderUsers); err != nil { 677 return false, nil, err 678 } 679 } 680 681 if !addNewReaderDevice && !addNewWriterDevice && !incKeyGen && 682 !handleChanged { 683 km.log.CDebugf(ctx, 684 "Skipping rekeying %s (private): no new or removed devices, no new keygen, and handle hasn't changed", 685 md.TlfID()) 686 return false, nil, nil 687 } 688 689 if !isWriter { 690 // This shouldn't happen; see the code above where we 691 // either use the original handle or resolve only the 692 // current UID. 693 if len(readersToPromote) != 0 { 694 return false, nil, errors.New( 695 "promoted readers unexpectedly non-empty") 696 } 697 698 if _, userHasNewKeys := newReaderUsers[session.UID]; userHasNewKeys { 699 // Only rekey the logged-in reader. 700 updatedWriterKeys = nil 701 updatedReaderKeys = kbfsmd.UserDevicePublicKeys{ 702 session.UID: updatedReaderKeys[session.UID], 703 } 704 delete(newReaderUsers, session.UID) 705 } else { 706 // No new reader device for our user, so the reader can't do 707 // anything 708 return false, nil, RekeyIncompleteError{} 709 } 710 } 711 712 // If promotedReader is non-empty, then isWriter is true (see 713 // check above). 714 err = md.promoteReaders(readersToPromote) 715 if err != nil { 716 return false, nil, err 717 } 718 719 // Generate ephemeral keys to be used by addNewDevice, 720 // incKeygen, or both. ePrivKey will be discarded at the end 721 // of the function. 722 ePubKey, ePrivKey, err := 723 km.config.Crypto().MakeRandomTLFEphemeralKeys() 724 725 // Note: For MDv3, if incKeyGen is true, then all the 726 // manipulations below aren't needed, since they'll just be 727 // replaced by the new key generation. However, do them 728 // anyway, as they may have some side effects, e.g. removing 729 // server key halves. 730 731 // If there's at least one new device, add that device to every key bundle. 732 if addNewReaderDevice || addNewWriterDevice { 733 start, end := md.KeyGenerationsToUpdate() 734 if start >= end { 735 return false, nil, errors.New( 736 "Unexpected empty range for key generations to update") 737 } 738 cryptKeys := make([]kbfscrypto.TLFCryptKey, end-start) 739 flags := getTLFCryptKeyAnyDevice 740 if promptPaper { 741 flags |= getTLFCryptKeyPromptPaper 742 } 743 for keyGen := start; keyGen < end; keyGen++ { 744 currTlfCryptKey, err := km.getTLFCryptKey( 745 ctx, md.ReadOnly(), keyGen, flags) 746 if err != nil { 747 return false, nil, err 748 } 749 cryptKeys[keyGen-start] = currTlfCryptKey 750 } 751 err = km.updateKeyBundles(ctx, md, updatedWriterKeys, 752 updatedReaderKeys, ePubKey, ePrivKey, cryptKeys) 753 if err != nil { 754 return false, nil, err 755 } 756 } 757 758 // Make sure the private MD is decrypted if it wasn't already. We 759 // have to do this here, before adding a new key generation, since 760 // decryptMDPrivateData assumes that the MD is always encrypted 761 // using the latest key gen. 762 if !md.IsReadable() && len(md.GetSerializedPrivateMetadata()) > 0 { 763 pmd, err := decryptMDPrivateData( 764 ctx, km.config.Codec(), km.config.Crypto(), 765 km.config.BlockCache(), km.config.BlockOps(), km, km.config.KBPKI(), 766 km.config, km.config.Mode(), session.UID, 767 md.GetSerializedPrivateMetadata(), md, md, km.log) 768 if err != nil { 769 return false, nil, err 770 } 771 md.data = pmd 772 } 773 774 defer func() { 775 // On our way back out, update the md with the 776 // resolved handle if at least part of a rekey was 777 // performed. Also, if we return true for mdChanged 778 // with a nil error or RekeyIncompleteError{}, we must 779 // call md.finalizeRekey() first. 780 781 _, isRekeyIncomplete := err.(RekeyIncompleteError) 782 if err == nil || isRekeyIncomplete { 783 updateErr := md.updateFromTlfHandle(resolvedHandle) 784 if updateErr != nil { 785 mdChanged = false 786 cryptKey = nil 787 err = updateErr 788 } 789 790 if mdChanged { 791 finalizeErr := md.finalizeRekey( 792 km.config.Codec()) 793 if finalizeErr != nil { 794 mdChanged = false 795 cryptKey = nil 796 err = finalizeErr 797 } 798 } 799 } 800 }() 801 802 if !isWriter { 803 if len(newReaderUsers) > 0 || addNewWriterDevice || incKeyGen { 804 // If we're a reader but we haven't completed all the work, return 805 // RekeyIncompleteError. 806 return addNewReaderDeviceForSelf, nil, RekeyIncompleteError{} 807 } 808 // Otherwise, there's nothing left to do! 809 return true, nil, nil 810 } else if !incKeyGen { 811 // we're done! 812 return true, nil, nil 813 } 814 815 // Send rekey start notification once we're sure that this device 816 // can perform the rekey. Don't send this for the first key 817 // generation though, since that's not really a "re"key. 818 // 819 // TODO: Shouldn't this happen earlier? 820 if currKeyGen >= kbfsmd.FirstValidKeyGen { 821 km.config.Reporter().Notify(ctx, rekeyNotification( 822 ctx, km.config, resolvedHandle, false)) 823 } 824 825 // Delete server-side key halves for any revoked devices, if 826 // there are any previous key generations. Do this before 827 // adding a new key generation, as MDv3 only keeps track of 828 // the latest key generation. 829 // 830 // TODO: Add test coverage for this. 831 if currKeyGen >= kbfsmd.FirstValidKeyGen { 832 allRemovalInfo, err := md.revokeRemovedDevices( 833 updatedWriterKeys, updatedReaderKeys) 834 if err != nil { 835 return false, nil, err 836 } 837 838 if len(allRemovalInfo) == 0 { 839 return false, nil, errors.New( 840 "Didn't revoke any devices, but indicated incrementing the key generation") 841 } 842 843 kops := km.config.KeyOps() 844 for uid, userRemovalInfo := range allRemovalInfo { 845 if userRemovalInfo.UserRemoved { 846 km.log.CInfof(ctx, "Rekey %s: removed user %s entirely", 847 md.TlfID(), uid) 848 } 849 for key, serverHalfIDs := range userRemovalInfo.DeviceServerHalfIDs { 850 km.log.CInfof(ctx, "Rekey %s: removing %d server key halves "+ 851 "for device %s of user %s", md.TlfID(), 852 len(serverHalfIDs), key, uid) 853 for _, serverHalfID := range serverHalfIDs { 854 err := kops.DeleteTLFCryptKeyServerHalf( 855 ctx, uid, key, serverHalfID) 856 if err != nil { 857 return false, nil, err 858 } 859 } 860 } 861 } 862 } 863 864 pubKey, privKey, tlfCryptKey, err := 865 km.config.Crypto().MakeRandomTLFKeys() 866 if err != nil { 867 return false, nil, err 868 } 869 870 // Get the current TLF crypt key if needed. It's 871 // symmetrically encrypted and appended to a list for MDv3 872 // metadata. 873 var currTLFCryptKey kbfscrypto.TLFCryptKey 874 if md.StoresHistoricTLFCryptKeys() && currKeyGen >= kbfsmd.FirstValidKeyGen { 875 flags := getTLFCryptKeyAnyDevice 876 if promptPaper { 877 flags |= getTLFCryptKeyPromptPaper 878 } 879 var err error 880 currTLFCryptKey, err = km.getTLFCryptKey( 881 ctx, md.ReadOnly(), currKeyGen, flags) 882 if err != nil { 883 return false, nil, err 884 } 885 } 886 serverHalves, err := md.AddKeyGeneration(km.config.Codec(), 887 updatedWriterKeys, updatedReaderKeys, 888 ePubKey, ePrivKey, pubKey, privKey, 889 currTLFCryptKey, tlfCryptKey) 890 if err != nil { 891 return false, nil, err 892 } 893 894 err = km.config.KeyOps().PutTLFCryptKeyServerHalves(ctx, serverHalves) 895 if err != nil { 896 return false, nil, err 897 } 898 899 return true, &tlfCryptKey, nil 900 }