github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/libkbfs/key_manager_test.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 "fmt" 9 "sync" 10 "testing" 11 "time" 12 13 "github.com/golang/mock/gomock" 14 "github.com/keybase/client/go/externals" 15 "github.com/keybase/client/go/kbfs/data" 16 "github.com/keybase/client/go/kbfs/idutil" 17 "github.com/keybase/client/go/kbfs/kbfsblock" 18 "github.com/keybase/client/go/kbfs/kbfscodec" 19 "github.com/keybase/client/go/kbfs/kbfscrypto" 20 "github.com/keybase/client/go/kbfs/kbfsmd" 21 libkeytest "github.com/keybase/client/go/kbfs/libkey/test" 22 "github.com/keybase/client/go/kbfs/test/clocktest" 23 "github.com/keybase/client/go/kbfs/tlf" 24 "github.com/keybase/client/go/kbfs/tlfhandle" 25 kbname "github.com/keybase/client/go/kbun" 26 "github.com/keybase/client/go/protocol/keybase1" 27 "github.com/pkg/errors" 28 "github.com/stretchr/testify/require" 29 "golang.org/x/net/context" 30 ) 31 32 type shimKMCrypto struct { 33 Crypto 34 pure cryptoPure 35 } 36 37 func mockNormalizeSocialAssertion(config *ConfigMock) { 38 config.mockKbpki.EXPECT().NormalizeSocialAssertion(gomock.Any(), gomock.Any()).DoAndReturn( 39 func(ctx context.Context, assertion string) (keybase1.SocialAssertion, error) { 40 socialAssertion, isSocialAssertion := externals.NormalizeSocialAssertionStatic(context.Background(), assertion) 41 if !isSocialAssertion { 42 return keybase1.SocialAssertion{}, fmt.Errorf("Invalid social assertion") 43 } 44 return socialAssertion, nil 45 }).AnyTimes() 46 } 47 48 func keyManagerInit(t *testing.T, ver kbfsmd.MetadataVer) (mockCtrl *gomock.Controller, 49 config *ConfigMock, ctx context.Context) { 50 ctr := NewSafeTestReporter(t) 51 mockCtrl = gomock.NewController(ctr) 52 config = NewConfigMock(mockCtrl, ctr) 53 keyCache := NewKeyCacheStandard(100) 54 config.SetKeyCache(keyCache) 55 keyman := NewKeyManagerStandard(config) 56 config.SetKeyManager(keyman) 57 interposeDaemonKBPKI(config, "alice", "bob", "charlie", "dave") 58 ctx = context.Background() 59 codec := kbfscodec.NewMsgpack() 60 config.SetCodec(codec) 61 cryptoPure := MakeCryptoCommon(codec, makeBlockCryptV1()) 62 config.SetCrypto(shimKMCrypto{config.Crypto(), cryptoPure}) 63 config.SetMetadataVersion(ver) 64 65 // Don't test implicit teams. 66 config.mockKbpki.EXPECT().ResolveImplicitTeam( 67 gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 68 AnyTimes().Return(idutil.ImplicitTeamInfo{}, errors.New("No such team")) 69 70 mockNormalizeSocialAssertion(config) 71 return mockCtrl, config, ctx 72 } 73 74 func keyManagerShutdown(mockCtrl *gomock.Controller, config *ConfigMock) { 75 config.ctr.CheckForFailures() 76 mockCtrl.Finish() 77 } 78 79 var serverHalf = kbfscrypto.MakeTLFCryptKeyServerHalf([32]byte{0x2}) 80 81 func expectUncachedGetTLFCryptKey(t *testing.T, config *ConfigMock, tlfID tlf.ID, keyGen, currKeyGen kbfsmd.KeyGen, 82 storesHistoric bool, tlfCryptKey, currTLFCryptKey kbfscrypto.TLFCryptKey) { 83 if keyGen == currKeyGen { 84 require.Equal(t, tlfCryptKey, currTLFCryptKey) 85 } 86 var keyToUse kbfscrypto.TLFCryptKey 87 if storesHistoric { 88 keyToUse = currTLFCryptKey 89 } else { 90 keyToUse = tlfCryptKey 91 } 92 clientHalf := kbfscrypto.MaskTLFCryptKey(serverHalf, keyToUse) 93 94 // get the xor'd key out of the metadata 95 config.mockCrypto.EXPECT().DecryptTLFCryptKeyClientHalf( 96 gomock.Any(), kbfscrypto.TLFEphemeralPublicKey{}, 97 gomock.Any()).Return(clientHalf, nil) 98 99 // get the server-side half and retrieve the real 100 // current secret key 101 config.mockKops.EXPECT().GetTLFCryptKeyServerHalf(gomock.Any(), 102 gomock.Any(), gomock.Any()).Return(serverHalf, nil) 103 } 104 105 func expectUncachedGetTLFCryptKeyAnyDevice( 106 config *ConfigMock, tlfID tlf.ID, keyGen kbfsmd.KeyGen, uid keybase1.UID, 107 subkey kbfscrypto.CryptPublicKey, tlfCryptKey kbfscrypto.TLFCryptKey) { 108 clientHalf := kbfscrypto.MaskTLFCryptKey(serverHalf, tlfCryptKey) 109 110 // get the xor'd key out of the metadata 111 config.mockKbpki.EXPECT().GetCryptPublicKeys( 112 gomock.Any(), uid, gomock.Any()). 113 Return([]kbfscrypto.CryptPublicKey{subkey}, nil) 114 config.mockCrypto.EXPECT().DecryptTLFCryptKeyClientHalfAny(gomock.Any(), 115 gomock.Any(), false).Return(clientHalf, 0, nil) 116 117 // get the server-side half and retrieve the real secret key 118 config.mockKops.EXPECT().GetTLFCryptKeyServerHalf(gomock.Any(), 119 gomock.Any(), gomock.Any()).Return(serverHalf, nil) 120 } 121 122 func expectRekey(config *ConfigMock, bh tlf.Handle, numDevices int, 123 handleChange, expectNewKeyGen bool, 124 tlfCryptKey kbfscrypto.TLFCryptKey) { 125 if handleChange { 126 // if the handle changes the key manager checks for a conflict 127 config.mockMdops.EXPECT().GetLatestHandleForTLF(gomock.Any(), gomock.Any()). 128 Return(bh, nil) 129 } 130 131 // generate new keys 132 config.mockCrypto.EXPECT().MakeRandomTLFEphemeralKeys().Return( 133 kbfscrypto.TLFEphemeralPublicKey{}, 134 kbfscrypto.TLFEphemeralPrivateKey{}, nil) 135 if expectNewKeyGen { 136 config.mockCrypto.EXPECT().MakeRandomTLFKeys().Return( 137 kbfscrypto.TLFPublicKey{}, kbfscrypto.TLFPrivateKey{}, 138 tlfCryptKey, nil) 139 } 140 141 subkey := kbfscrypto.MakeFakeCryptPublicKeyOrBust("crypt public key") 142 config.mockKbpki.EXPECT().GetCryptPublicKeys( 143 gomock.Any(), gomock.Any(), gomock.Any()). 144 Return([]kbfscrypto.CryptPublicKey{subkey}, nil).Times(numDevices) 145 146 // make keys for the one device 147 config.mockKops.EXPECT().PutTLFCryptKeyServerHalves(gomock.Any(), gomock.Any()).Return(nil) 148 149 // Ignore Notify and Flush calls for now 150 config.mockRep.EXPECT().Notify(gomock.Any(), gomock.Any()).AnyTimes() 151 config.mockKbs.EXPECT().FlushUserFromLocalCache(gomock.Any(), 152 gomock.Any()).AnyTimes() 153 } 154 155 func testKeyManagerPublicTLFCryptKey(t *testing.T, ver kbfsmd.MetadataVer) { 156 mockCtrl, config, ctx := keyManagerInit(t, ver) 157 defer keyManagerShutdown(mockCtrl, config) 158 159 id := tlf.FakeID(1, tlf.Public) 160 kmd := libkeytest.NewEmptyKeyMetadata(id, 1) 161 162 tlfCryptKey, err := config.KeyManager(). 163 GetTLFCryptKeyForEncryption(ctx, kmd) 164 if err != nil { 165 t.Error(err) 166 } 167 168 if tlfCryptKey != kbfscrypto.PublicTLFCryptKey { 169 t.Errorf("got %v, expected %v", 170 tlfCryptKey, kbfscrypto.PublicTLFCryptKey) 171 } 172 173 tlfCryptKey, err = config.KeyManager(). 174 GetTLFCryptKeyForMDDecryption(ctx, kmd, kmd) 175 if err != nil { 176 t.Error(err) 177 } 178 179 if tlfCryptKey != kbfscrypto.PublicTLFCryptKey { 180 t.Errorf("got %v, expected %v", 181 tlfCryptKey, kbfscrypto.PublicTLFCryptKey) 182 } 183 184 tlfCryptKey, err = config.KeyManager(). 185 GetTLFCryptKeyForBlockDecryption(ctx, kmd, data.BlockPointer{}) 186 if err != nil { 187 t.Error(err) 188 } 189 190 if tlfCryptKey != kbfscrypto.PublicTLFCryptKey { 191 t.Errorf("got %v, expected %v", 192 tlfCryptKey, kbfscrypto.PublicTLFCryptKey) 193 } 194 } 195 196 func testKeyManagerCachedSecretKeyForEncryptionSuccess(t *testing.T, ver kbfsmd.MetadataVer) { 197 mockCtrl, config, ctx := keyManagerInit(t, ver) 198 defer keyManagerShutdown(mockCtrl, config) 199 200 id := tlf.FakeID(1, tlf.Private) 201 kmd := libkeytest.NewEmptyKeyMetadata(id, 1) 202 203 cachedTLFCryptKey := kbfscrypto.MakeTLFCryptKey([32]byte{0x1}) 204 err := config.KeyCache().PutTLFCryptKey(id, 1, cachedTLFCryptKey) 205 require.NoError(t, err) 206 207 tlfCryptKey, err := config.KeyManager(). 208 GetTLFCryptKeyForEncryption(ctx, kmd) 209 require.NoError(t, err) 210 require.Equal(t, cachedTLFCryptKey, tlfCryptKey) 211 } 212 213 func testKeyManagerCachedSecretKeyForMDDecryptionSuccess(t *testing.T, ver kbfsmd.MetadataVer) { 214 mockCtrl, config, ctx := keyManagerInit(t, ver) 215 defer keyManagerShutdown(mockCtrl, config) 216 217 id := tlf.FakeID(1, tlf.Private) 218 kmd := libkeytest.NewEmptyKeyMetadata(id, 1) 219 220 cachedTLFCryptKey := kbfscrypto.MakeTLFCryptKey([32]byte{0x1}) 221 err := config.KeyCache().PutTLFCryptKey(id, 1, cachedTLFCryptKey) 222 require.NoError(t, err) 223 224 tlfCryptKey, err := config.KeyManager(). 225 GetTLFCryptKeyForMDDecryption(ctx, kmd, kmd) 226 require.NoError(t, err) 227 require.Equal(t, cachedTLFCryptKey, tlfCryptKey) 228 } 229 230 func testKeyManagerCachedSecretKeyForBlockDecryptionSuccess(t *testing.T, ver kbfsmd.MetadataVer) { 231 mockCtrl, config, ctx := keyManagerInit(t, ver) 232 defer keyManagerShutdown(mockCtrl, config) 233 234 id := tlf.FakeID(1, tlf.Private) 235 kmd := libkeytest.NewEmptyKeyMetadata(id, 2) 236 237 cachedTLFCryptKey := kbfscrypto.MakeTLFCryptKey([32]byte{0x1}) 238 err := config.KeyCache().PutTLFCryptKey(id, 1, cachedTLFCryptKey) 239 require.NoError(t, err) 240 241 tlfCryptKey, err := config.KeyManager().GetTLFCryptKeyForBlockDecryption( 242 ctx, kmd, data.BlockPointer{KeyGen: 1}) 243 require.NoError(t, err) 244 require.Equal(t, cachedTLFCryptKey, tlfCryptKey) 245 } 246 247 // makeDirWKeyInfoMap creates a new user device key info map with a writer key. 248 func makeDirWKeyInfoMap(uid keybase1.UID, 249 cryptPublicKey kbfscrypto.CryptPublicKey) kbfsmd.UserDevicePublicKeys { 250 return kbfsmd.UserDevicePublicKeys{ 251 uid: { 252 cryptPublicKey: true, 253 }, 254 } 255 } 256 257 func testKeyManagerUncachedSecretKeyForEncryptionSuccess(t *testing.T, ver kbfsmd.MetadataVer) { 258 mockCtrl, config, ctx := keyManagerInit(t, ver) 259 defer keyManagerShutdown(mockCtrl, config) 260 261 id := tlf.FakeID(1, tlf.Private) 262 h := parseTlfHandleOrBust(t, config, "alice", tlf.Private, id) 263 uid := h.FirstResolvedWriter() 264 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 265 require.NoError(t, err) 266 267 session, err := config.KBPKI().GetCurrentSession(ctx) 268 require.NoError(t, err) 269 storedTLFCryptKey := kbfscrypto.MakeTLFCryptKey([32]byte{0x1}) 270 271 _, err = rmd.AddKeyGeneration(config.Codec(), 272 makeDirWKeyInfoMap(uid.AsUserOrBust(), session.CryptPublicKey), 273 kbfsmd.UserDevicePublicKeys{}, 274 kbfscrypto.TLFEphemeralPublicKey{}, 275 kbfscrypto.TLFEphemeralPrivateKey{}, 276 kbfscrypto.TLFPublicKey{}, kbfscrypto.TLFPrivateKey{}, 277 kbfscrypto.TLFCryptKey{}, storedTLFCryptKey) 278 require.NoError(t, err) 279 280 storesHistoric := rmd.StoresHistoricTLFCryptKeys() 281 expectUncachedGetTLFCryptKey(t, config, rmd.TlfID(), 282 rmd.LatestKeyGeneration(), rmd.LatestKeyGeneration(), 283 storesHistoric, storedTLFCryptKey, storedTLFCryptKey) 284 285 tlfCryptKey, err := config.KeyManager().GetTLFCryptKeyForEncryption(ctx, rmd) 286 require.NoError(t, err) 287 require.Equal(t, storedTLFCryptKey, tlfCryptKey) 288 } 289 290 func testKeyManagerUncachedSecretKeyForMDDecryptionSuccess(t *testing.T, ver kbfsmd.MetadataVer) { 291 mockCtrl, config, ctx := keyManagerInit(t, ver) 292 defer keyManagerShutdown(mockCtrl, config) 293 294 id := tlf.FakeID(1, tlf.Private) 295 h := parseTlfHandleOrBust(t, config, "alice", tlf.Private, id) 296 uid := h.FirstResolvedWriter() 297 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 298 require.NoError(t, err) 299 300 subkey := kbfscrypto.MakeFakeCryptPublicKeyOrBust("crypt public key") 301 storedTLFCryptKey := kbfscrypto.MakeTLFCryptKey([32]byte{0x1}) 302 303 _, err = rmd.AddKeyGeneration(config.Codec(), 304 makeDirWKeyInfoMap(uid.AsUserOrBust(), subkey), kbfsmd.UserDevicePublicKeys{}, 305 kbfscrypto.TLFEphemeralPublicKey{}, 306 kbfscrypto.TLFEphemeralPrivateKey{}, 307 kbfscrypto.TLFPublicKey{}, kbfscrypto.TLFPrivateKey{}, 308 kbfscrypto.TLFCryptKey{}, storedTLFCryptKey) 309 require.NoError(t, err) 310 311 expectUncachedGetTLFCryptKeyAnyDevice( 312 config, rmd.TlfID(), rmd.LatestKeyGeneration(), uid.AsUserOrBust(), 313 subkey, storedTLFCryptKey) 314 315 tlfCryptKey, err := config.KeyManager(). 316 GetTLFCryptKeyForMDDecryption(ctx, rmd, rmd) 317 require.NoError(t, err) 318 require.Equal(t, storedTLFCryptKey, tlfCryptKey) 319 } 320 321 func testKeyManagerUncachedSecretKeyForBlockDecryptionSuccess(t *testing.T, ver kbfsmd.MetadataVer) { 322 mockCtrl, config, ctx := keyManagerInit(t, ver) 323 defer keyManagerShutdown(mockCtrl, config) 324 325 id := tlf.FakeID(1, tlf.Private) 326 h := parseTlfHandleOrBust(t, config, "alice", tlf.Private, id) 327 uid := h.FirstResolvedWriter() 328 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 329 require.NoError(t, err) 330 331 session, err := config.KBPKI().GetCurrentSession(ctx) 332 require.NoError(t, err) 333 storedTLFCryptKey1 := kbfscrypto.MakeTLFCryptKey([32]byte{0x1}) 334 storedTLFCryptKey2 := kbfscrypto.MakeTLFCryptKey([32]byte{0x2}) 335 336 _, err = rmd.AddKeyGeneration(config.Codec(), 337 makeDirWKeyInfoMap(uid.AsUserOrBust(), session.CryptPublicKey), 338 kbfsmd.UserDevicePublicKeys{}, 339 kbfscrypto.TLFEphemeralPublicKey{}, 340 kbfscrypto.TLFEphemeralPrivateKey{}, 341 kbfscrypto.TLFPublicKey{}, kbfscrypto.TLFPrivateKey{}, 342 kbfscrypto.TLFCryptKey{}, storedTLFCryptKey1) 343 require.NoError(t, err) 344 345 var currCryptKey kbfscrypto.TLFCryptKey 346 if rmd.StoresHistoricTLFCryptKeys() { 347 currCryptKey = storedTLFCryptKey1 348 } 349 _, err = rmd.AddKeyGeneration(config.Codec(), 350 makeDirWKeyInfoMap(uid.AsUserOrBust(), session.CryptPublicKey), 351 kbfsmd.UserDevicePublicKeys{}, 352 kbfscrypto.TLFEphemeralPublicKey{}, 353 kbfscrypto.TLFEphemeralPrivateKey{}, 354 kbfscrypto.TLFPublicKey{}, kbfscrypto.TLFPrivateKey{}, 355 currCryptKey, storedTLFCryptKey2) 356 require.NoError(t, err) 357 358 keyGen := rmd.LatestKeyGeneration() - 1 359 storesHistoric := rmd.StoresHistoricTLFCryptKeys() 360 expectUncachedGetTLFCryptKey(t, config, rmd.TlfID(), keyGen, 361 rmd.LatestKeyGeneration(), storesHistoric, storedTLFCryptKey1, 362 storedTLFCryptKey2) 363 364 tlfCryptKey, err := config.KeyManager().GetTLFCryptKeyForBlockDecryption( 365 ctx, rmd, data.BlockPointer{KeyGen: 1}) 366 require.NoError(t, err) 367 require.Equal(t, storedTLFCryptKey1, tlfCryptKey) 368 } 369 370 func testKeyManagerRekeySuccessPrivate(t *testing.T, ver kbfsmd.MetadataVer) { 371 mockCtrl, config, ctx := keyManagerInit(t, ver) 372 defer keyManagerShutdown(mockCtrl, config) 373 374 id := tlf.FakeID(1, tlf.Private) 375 h := parseTlfHandleOrBust(t, config, "alice", tlf.Private, id) 376 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 377 require.NoError(t, err) 378 379 oldKeyGen := rmd.LatestKeyGeneration() 380 381 tlfCryptKey := kbfscrypto.MakeTLFCryptKey([32]byte{0x1}) 382 expectRekey(config, h.ToBareHandleOrBust(), 1, false, true, tlfCryptKey) 383 384 if done, _, err := config.KeyManager().Rekey(ctx, rmd, false); !done || err != nil { 385 t.Errorf("Got error on rekey: %t, %+v", done, err) 386 } else if rmd.LatestKeyGeneration() != oldKeyGen+1 { 387 t.Errorf("Bad key generation after rekey: %d", rmd.LatestKeyGeneration()) 388 } 389 } 390 391 func testKeyManagerRekeyResolveAgainSuccessPublic(t *testing.T, ver kbfsmd.MetadataVer) { 392 mockCtrl, config, ctx := keyManagerInit(t, ver) 393 defer keyManagerShutdown(mockCtrl, config) 394 395 id := tlf.FakeID(1, tlf.Public) 396 h, err := tlfhandle.ParseHandle( 397 ctx, config.KBPKI(), tlfhandle.ConstIDGetter{ID: id}, nil, 398 "alice,bob@twitter", tlf.Public) 399 require.NoError(t, err) 400 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 401 require.NoError(t, err) 402 403 daemon := config.KeybaseService().(*KeybaseDaemonLocal) 404 daemon.AddNewAssertionForTestOrBust("bob", "bob@twitter") 405 406 config.mockMdops.EXPECT().GetLatestHandleForTLF(gomock.Any(), gomock.Any()). 407 Return(rmd.tlfHandle.ToBareHandleOrBust(), nil) 408 409 done, cryptKey, err := config.KeyManager().Rekey(ctx, rmd, false) 410 require.NoError(t, err) 411 require.True(t, done) 412 require.Nil(t, cryptKey) 413 414 newH := rmd.GetTlfHandle() 415 require.Equal(t, tlf.CanonicalName("alice,bob"), newH.GetCanonicalName()) 416 417 // Also check MakeBareTlfHandle. 418 oldHandle := rmd.tlfHandle 419 rmd.tlfHandle = nil 420 newBareH, err := rmd.MakeBareTlfHandle() 421 require.NoError(t, err) 422 require.Equal(t, newH.ToBareHandleOrBust(), newBareH) 423 rmd.tlfHandle = oldHandle 424 425 // Rekey again, which shouldn't do anything. 426 done, cryptKey, err = config.KeyManager().Rekey(ctx, rmd, false) 427 require.False(t, done) 428 require.Nil(t, cryptKey) 429 require.NoError(t, err) 430 } 431 432 func testKeyManagerRekeyResolveAgainSuccessPublicSelf(t *testing.T, ver kbfsmd.MetadataVer) { 433 mockCtrl, config, ctx := keyManagerInit(t, ver) 434 defer keyManagerShutdown(mockCtrl, config) 435 436 id := tlf.FakeID(1, tlf.Public) 437 h, err := tlfhandle.ParseHandle( 438 ctx, config.KBPKI(), tlfhandle.ConstIDGetter{ID: id}, nil, 439 "alice@twitter,bob,charlie@twitter", tlf.Public) 440 require.NoError(t, err) 441 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 442 require.NoError(t, err) 443 444 daemon := config.KeybaseService().(*KeybaseDaemonLocal) 445 daemon.AddNewAssertionForTestOrBust("alice", "alice@twitter") 446 daemon.AddNewAssertionForTestOrBust("charlie", "charlie@twitter") 447 448 config.mockMdops.EXPECT().GetLatestHandleForTLF(gomock.Any(), gomock.Any()). 449 Return(rmd.tlfHandle.ToBareHandleOrBust(), nil) 450 451 done, cryptKey, err := config.KeyManager().Rekey(ctx, rmd, false) 452 require.True(t, done) 453 require.Nil(t, cryptKey) 454 require.NoError(t, err) 455 456 newH := rmd.GetTlfHandle() 457 require.Equal(t, tlf.CanonicalName("alice,bob,charlie"), newH.GetCanonicalName()) 458 459 // Also check MakeBareTlfHandle. 460 oldHandle := rmd.tlfHandle 461 rmd.tlfHandle = nil 462 newBareH, err := rmd.MakeBareTlfHandle() 463 require.NoError(t, err) 464 require.Equal(t, newH.ToBareHandleOrBust(), newBareH) 465 rmd.tlfHandle = oldHandle 466 } 467 468 func testKeyManagerRekeyResolveAgainSuccessPrivate(t *testing.T, ver kbfsmd.MetadataVer) { 469 mockCtrl, config, ctx := keyManagerInit(t, ver) 470 defer keyManagerShutdown(mockCtrl, config) 471 472 id := tlf.FakeID(1, tlf.Private) 473 h, err := tlfhandle.ParseHandle( 474 ctx, config.KBPKI(), tlfhandle.ConstIDGetter{ID: id}, nil, 475 "alice,bob@twitter,dave@twitter#charlie@twitter", tlf.Private) 476 if err != nil { 477 t.Fatal(err) 478 } 479 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 480 require.NoError(t, err) 481 482 oldKeyGen := rmd.LatestKeyGeneration() 483 484 tlfCryptKey1 := kbfscrypto.MakeTLFCryptKey([32]byte{0x1}) 485 expectRekey(config, h.ToBareHandleOrBust(), 3, true, true, tlfCryptKey1) 486 487 // Pretend that {bob,charlie}@twitter now resolve to {bob,charlie}. 488 daemon := config.KeybaseService().(*KeybaseDaemonLocal) 489 daemon.AddNewAssertionForTestOrBust("bob", "bob@twitter") 490 daemon.AddNewAssertionForTestOrBust("charlie", "charlie@twitter") 491 492 if done, _, err := config.KeyManager().Rekey(ctx, rmd, false); !done || err != nil { 493 t.Fatalf("Got error on rekey: %t, %+v", done, err) 494 } 495 496 if rmd.LatestKeyGeneration() != oldKeyGen+1 { 497 t.Fatalf("Bad key generation after rekey: %d", rmd.LatestKeyGeneration()) 498 } 499 500 newH := rmd.GetTlfHandle() 501 require.Equal(t, tlf.CanonicalName("alice,bob,dave@twitter#charlie"), 502 newH.GetCanonicalName()) 503 504 // Also check MakeBareTlfHandle. 505 oldHandle := rmd.tlfHandle 506 rmd.tlfHandle = nil 507 newBareH, err := rmd.MakeBareTlfHandle() 508 require.NoError(t, err) 509 require.Equal(t, newH.ToBareHandleOrBust(), newBareH) 510 rmd.tlfHandle = oldHandle 511 512 // Now resolve using only a device addition, which won't bump the 513 // generation number. 514 daemon.AddNewAssertionForTestOrBust("dave", "dave@twitter") 515 oldKeyGen = rmd.LatestKeyGeneration() 516 517 tlfCryptKey2 := kbfscrypto.MakeTLFCryptKey([32]byte{0x2}) 518 err = config.KeyCache().PutTLFCryptKey(id, 1, tlfCryptKey2) 519 require.NoError(t, err) 520 521 expectRekey(config, oldHandle.ToBareHandleOrBust(), 1, true, false, tlfCryptKey2) 522 subkey := kbfscrypto.MakeFakeCryptPublicKeyOrBust("crypt public key") 523 config.mockKbpki.EXPECT().GetCryptPublicKeys( 524 gomock.Any(), gomock.Any(), gomock.Any()). 525 Return([]kbfscrypto.CryptPublicKey{subkey}, nil).Times(3) 526 if done, _, err := 527 config.KeyManager().Rekey(ctx, rmd, false); !done || err != nil { 528 t.Fatalf("Got error on rekey: %t, %+v", done, err) 529 } 530 531 if rmd.LatestKeyGeneration() != oldKeyGen { 532 t.Fatalf("Bad key generation after rekey: %d", 533 rmd.LatestKeyGeneration()) 534 } 535 536 newH = rmd.GetTlfHandle() 537 require.Equal(t, tlf.CanonicalName("alice,bob,dave#charlie"), 538 newH.GetCanonicalName()) 539 540 // Also check MakeBareTlfHandle. 541 rmd.tlfHandle = nil 542 newBareH, err = rmd.MakeBareTlfHandle() 543 require.NoError(t, err) 544 require.Equal(t, newH.ToBareHandleOrBust(), newBareH) 545 } 546 547 func hasWriterKey(t *testing.T, rmd *RootMetadata, uid keybase1.UID) bool { 548 writers, _, err := rmd.getUserDevicePublicKeys() 549 require.NoError(t, err) 550 return len(writers[uid]) > 0 551 } 552 553 func testKeyManagerPromoteReaderSuccess(t *testing.T, ver kbfsmd.MetadataVer) { 554 ctx := context.Background() 555 556 config := MakeTestConfigOrBust(t, "alice", "bob") 557 defer CheckConfigAndShutdown(ctx, t, config) 558 559 id := tlf.FakeID(1, tlf.Private) 560 h, err := tlfhandle.ParseHandle( 561 ctx, config.KBPKI(), tlfhandle.ConstIDGetter{ID: id}, nil, 562 "alice,bob@twitter#bob", tlf.Private) 563 require.NoError(t, err) 564 565 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 566 require.NoError(t, err) 567 568 // Make the first key generation. 569 done, _, err := config.KeyManager().Rekey(ctx, rmd, false) 570 require.NoError(t, err) 571 require.True(t, done) 572 573 aliceUID := keybase1.MakeTestUID(1) 574 bobUID := keybase1.MakeTestUID(2) 575 576 require.True(t, hasWriterKey(t, rmd, aliceUID)) 577 require.False(t, hasWriterKey(t, rmd, bobUID)) 578 579 oldKeyGen := rmd.LatestKeyGeneration() 580 581 // Pretend that bob@twitter now resolves to bob. 582 daemon := config.KeybaseService().(*KeybaseDaemonLocal) 583 daemon.AddNewAssertionForTestOrBust("bob", "bob@twitter") 584 585 // Rekey as alice. 586 done, _, err = config.KeyManager().Rekey(ctx, rmd, false) 587 require.NoError(t, err) 588 require.True(t, done) 589 590 // Reader promotion shouldn't increase the key generation. 591 require.Equal(t, oldKeyGen, rmd.LatestKeyGeneration()) 592 593 require.True(t, hasWriterKey(t, rmd, aliceUID)) 594 require.True(t, hasWriterKey(t, rmd, bobUID)) 595 596 newH := rmd.GetTlfHandle() 597 require.Equal(t, 598 tlf.CanonicalName("alice,bob"), 599 newH.GetCanonicalName()) 600 } 601 602 func testKeyManagerPromoteReaderSelf(t *testing.T, ver kbfsmd.MetadataVer) { 603 ctx := context.Background() 604 605 config := MakeTestConfigOrBust(t, "alice", "bob") 606 defer CheckConfigAndShutdown(ctx, t, config) 607 608 id := tlf.FakeID(1, tlf.Private) 609 h, err := tlfhandle.ParseHandle( 610 ctx, config.KBPKI(), tlfhandle.ConstIDGetter{ID: id}, nil, 611 "alice,bob@twitter#bob", tlf.Private) 612 require.NoError(t, err) 613 614 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 615 require.NoError(t, err) 616 617 // Make the first key generation. 618 done, _, err := config.KeyManager().Rekey(ctx, rmd, false) 619 require.NoError(t, err) 620 require.True(t, done) 621 622 aliceUID := keybase1.MakeTestUID(1) 623 bobUID := keybase1.MakeTestUID(2) 624 625 require.True(t, hasWriterKey(t, rmd, aliceUID)) 626 require.False(t, hasWriterKey(t, rmd, bobUID)) 627 628 oldKeyGen := rmd.LatestKeyGeneration() 629 630 config2 := ConfigAsUser(config, "bob") 631 defer CheckConfigAndShutdown(ctx, t, config2) 632 633 // Pretend that bob@twitter now resolves to bob. 634 daemon := config2.KeybaseService().(*KeybaseDaemonLocal) 635 daemon.AddNewAssertionForTestOrBust("bob", "bob@twitter") 636 637 // Rekey as bob, which should still succeed. 638 done, _, err = config2.KeyManager().Rekey(ctx, rmd, false) 639 require.NoError(t, err) 640 require.True(t, done) 641 642 // Reader promotion shouldn't increase the key generation. 643 require.Equal(t, oldKeyGen, rmd.LatestKeyGeneration()) 644 645 require.True(t, hasWriterKey(t, rmd, aliceUID)) 646 require.True(t, hasWriterKey(t, rmd, bobUID)) 647 648 newH := rmd.GetTlfHandle() 649 require.Equal(t, 650 tlf.CanonicalName("alice,bob"), 651 newH.GetCanonicalName()) 652 } 653 654 func testKeyManagerReaderRekeyShouldNotPromote(t *testing.T, ver kbfsmd.MetadataVer) { 655 ctx := context.Background() 656 657 config := MakeTestConfigOrBust(t, "alice", "bob", "charlie") 658 defer CheckConfigAndShutdown(ctx, t, config) 659 660 id := tlf.FakeID(1, tlf.Private) 661 h, err := tlfhandle.ParseHandle( 662 ctx, config.KBPKI(), tlfhandle.ConstIDGetter{ID: id}, nil, 663 "alice,charlie@twitter#bob,charlie", tlf.Private) 664 require.NoError(t, err) 665 666 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 667 require.NoError(t, err) 668 669 // Make the first key generation. 670 done, _, err := config.KeyManager().Rekey(ctx, rmd, false) 671 require.NoError(t, err) 672 require.True(t, done) 673 674 aliceUID := keybase1.MakeTestUID(1) 675 bobUID := keybase1.MakeTestUID(2) 676 charlieUID := keybase1.MakeTestUID(3) 677 678 require.True(t, hasWriterKey(t, rmd, aliceUID)) 679 require.False(t, hasWriterKey(t, rmd, bobUID)) 680 require.False(t, hasWriterKey(t, rmd, charlieUID)) 681 682 config2 := ConfigAsUser(config, "bob") 683 defer CheckConfigAndShutdown(ctx, t, config2) 684 685 // Pretend that charlie@twitter now resolves to charlie. 686 daemon := config2.KeybaseService().(*KeybaseDaemonLocal) 687 daemon.AddNewAssertionForTestOrBust("charlie", "charlie@twitter") 688 689 AddDeviceForLocalUserOrBust(t, config2, bobUID) 690 691 // Try to rekey as bob, which should succeed partially. 692 done, _, err = config2.KeyManager().Rekey(ctx, rmd, false) 693 require.NoError(t, err) 694 require.True(t, done) 695 696 require.True(t, hasWriterKey(t, rmd, aliceUID)) 697 require.False(t, hasWriterKey(t, rmd, bobUID)) 698 require.False(t, hasWriterKey(t, rmd, charlieUID)) 699 } 700 701 func testKeyManagerReaderRekeyResolveAgainSuccessPrivate(t *testing.T, ver kbfsmd.MetadataVer) { 702 mockCtrl, config, ctx := keyManagerInit(t, ver) 703 defer keyManagerShutdown(mockCtrl, config) 704 705 id := tlf.FakeID(1, tlf.Private) 706 h, err := tlfhandle.ParseHandle( 707 ctx, config.KBPKI(), tlfhandle.ConstIDGetter{ID: id}, nil, 708 "alice,dave@twitter#bob@twitter,charlie@twitter", tlf.Private) 709 if err != nil { 710 t.Fatal(err) 711 } 712 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 713 require.NoError(t, err) 714 715 oldKeyGen := rmd.LatestKeyGeneration() 716 717 tlfCryptKey1 := kbfscrypto.MakeTLFCryptKey([32]byte{0x1}) 718 expectRekey(config, h.ToBareHandleOrBust(), 1, true, true, tlfCryptKey1) 719 720 // Make the first key generation 721 if done, _, err := config.KeyManager().Rekey(ctx, rmd, false); !done || err != nil { 722 t.Fatalf("Got error on rekey: %t, %+v", done, err) 723 } 724 725 if rmd.LatestKeyGeneration() != oldKeyGen+1 { 726 t.Fatalf("Bad key generation after rekey: %d", rmd.LatestKeyGeneration()) 727 } 728 729 newH := rmd.GetTlfHandle() 730 require.Equal(t, 731 tlf.CanonicalName("alice,dave@twitter#bob@twitter,charlie@twitter"), 732 newH.GetCanonicalName()) 733 734 // Now resolve everyone, but have reader bob to do the rekey 735 daemon := config.KeybaseService().(*KeybaseDaemonLocal) 736 daemon.AddNewAssertionForTestOrBust("bob", "bob@twitter") 737 daemon.AddNewAssertionForTestOrBust("charlie", "charlie@twitter") 738 daemon.AddNewAssertionForTestOrBust("dave", "dave@twitter") 739 740 _, bobID, err := daemon.Resolve( 741 ctx, "bob", keybase1.OfflineAvailability_NONE) 742 require.NoError(t, err) 743 bobUID, err := bobID.AsUser() 744 require.NoError(t, err) 745 daemon.SetCurrentUID(bobUID) 746 747 // Now resolve using only a device addition, which won't bump the 748 // generation number. 749 oldKeyGen = rmd.LatestKeyGeneration() 750 // Pretend bob has the key in the cache (in reality it would be 751 // decrypted via bob's paper key) 752 753 tlfCryptKey2 := kbfscrypto.MakeTLFCryptKey([32]byte{0x2}) 754 err = config.KeyCache().PutTLFCryptKey(rmd.TlfID(), oldKeyGen, tlfCryptKey2) 755 require.NoError(t, err) 756 757 expectRekey(config, h.ToBareHandleOrBust(), 1, false, false, tlfCryptKey2) 758 subkey := kbfscrypto.MakeFakeCryptPublicKeyOrBust("crypt public key") 759 config.mockKbpki.EXPECT().GetCryptPublicKeys( 760 gomock.Any(), gomock.Any(), gomock.Any()). 761 Return([]kbfscrypto.CryptPublicKey{subkey}, nil) 762 if done, _, err := 763 config.KeyManager().Rekey(ctx, rmd, false); !done || err != nil { 764 t.Fatalf("Got error on rekey: %t, %+v", done, err) 765 } 766 767 if rmd.LatestKeyGeneration() != oldKeyGen { 768 t.Fatalf("Bad key generation after rekey: %d", 769 rmd.LatestKeyGeneration()) 770 } 771 772 // bob shouldn't have been able to resolve other users since he's 773 // just a reader. 774 newH = rmd.GetTlfHandle() 775 require.Equal(t, tlf.CanonicalName("alice,dave@twitter#bob,charlie@twitter"), 776 newH.GetCanonicalName()) 777 778 // Also check MakeBareTlfHandle. 779 rmd.tlfHandle = nil 780 newBareH, err := rmd.MakeBareTlfHandle() 781 require.NoError(t, err) 782 require.Equal(t, newH.ToBareHandleOrBust(), newBareH) 783 } 784 785 func testKeyManagerRekeyResolveAgainNoChangeSuccessPrivate(t *testing.T, ver kbfsmd.MetadataVer) { 786 mockCtrl, config, ctx := keyManagerInit(t, ver) 787 defer keyManagerShutdown(mockCtrl, config) 788 789 id := tlf.FakeID(1, tlf.Private) 790 h, err := tlfhandle.ParseHandle( 791 ctx, config.KBPKI(), tlfhandle.ConstIDGetter{ID: id}, nil, 792 "alice,bob,bob@twitter", tlf.Private) 793 if err != nil { 794 t.Fatal(err) 795 } 796 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 797 require.NoError(t, err) 798 799 oldKeyGen := rmd.LatestKeyGeneration() 800 801 tlfCryptKey1 := kbfscrypto.MakeTLFCryptKey([32]byte{0x1}) 802 expectRekey(config, h.ToBareHandleOrBust(), 2, true, true, tlfCryptKey1) 803 804 // Make the first key generation 805 if done, _, err := config.KeyManager().Rekey(ctx, rmd, false); !done || err != nil { 806 t.Fatalf("Got error on rekey: %t, %+v", done, err) 807 } 808 809 if rmd.LatestKeyGeneration() != oldKeyGen+1 { 810 t.Fatalf("Bad key generation after rekey: %d", rmd.LatestKeyGeneration()) 811 } 812 813 newH := rmd.GetTlfHandle() 814 require.Equal(t, 815 tlf.CanonicalName("alice,bob,bob@twitter"), 816 newH.GetCanonicalName()) 817 818 // Now resolve everyone, but have reader bob to do the rekey 819 daemon := config.KeybaseService().(*KeybaseDaemonLocal) 820 daemon.AddNewAssertionForTestOrBust("bob", "bob@twitter") 821 822 // Now resolve which gets rid of the unresolved writers, but 823 // doesn't otherwise change the handle since bob is already in it. 824 oldKeyGen = rmd.LatestKeyGeneration() 825 config.mockCrypto.EXPECT().MakeRandomTLFEphemeralKeys().Return( 826 kbfscrypto.TLFEphemeralPublicKey{}, 827 kbfscrypto.TLFEphemeralPrivateKey{}, nil) 828 829 subkey := kbfscrypto.MakeFakeCryptPublicKeyOrBust("crypt public key") 830 config.mockKbpki.EXPECT().GetCryptPublicKeys( 831 gomock.Any(), gomock.Any(), gomock.Any()). 832 Return([]kbfscrypto.CryptPublicKey{subkey}, nil).Times(2) 833 if done, _, err := 834 config.KeyManager().Rekey(ctx, rmd, false); !done || err != nil { 835 t.Fatalf("Got error on rekey: %t, %+v", done, err) 836 } 837 838 if rmd.LatestKeyGeneration() != oldKeyGen { 839 t.Fatalf("Bad key generation after rekey: %d", 840 rmd.LatestKeyGeneration()) 841 } 842 843 // bob shouldn't have been able to resolve other users since he's 844 // just a reader. 845 newH = rmd.GetTlfHandle() 846 require.Equal(t, tlf.CanonicalName("alice,bob"), newH.GetCanonicalName()) 847 848 // Also check MakeBareTlfHandle. 849 rmd.tlfHandle = nil 850 newBareH, err := rmd.MakeBareTlfHandle() 851 require.NoError(t, err) 852 require.Equal(t, newH.ToBareHandleOrBust(), newBareH) 853 } 854 855 func testKeyManagerRekeyAddAndRevokeDevice(t *testing.T, ver kbfsmd.MetadataVer) { 856 var u1, u2 kbname.NormalizedUsername = "u1", "u2" 857 config1, _, ctx, cancel := kbfsOpsConcurInit(t, u1, u2) 858 defer kbfsConcurTestShutdown(ctx, t, config1, cancel) 859 clock := clocktest.NewTestClockNow() 860 config1.SetClock(clock) 861 862 config1.SetMetadataVersion(ver) 863 864 config2 := ConfigAsUser(config1, u2) 865 defer CheckConfigAndShutdown(ctx, t, config2) 866 session2, err := config2.KBPKI().GetCurrentSession(ctx) 867 if err != nil { 868 t.Fatal(err) 869 } 870 uid2 := session2.UID 871 872 // Create a shared folder 873 name := u1.String() + "," + u2.String() 874 875 rootNode1 := GetRootNodeOrBust(ctx, t, config1, name, tlf.Private) 876 877 kbfsOps1 := config1.KBFSOps() 878 879 // user 1 creates a file 880 _, _, err = kbfsOps1.CreateFile(ctx, rootNode1, testPPS("a"), false, NoExcl) 881 if err != nil { 882 t.Fatalf("Couldn't create file: %+v", err) 883 } 884 err = kbfsOps1.SyncAll(ctx, rootNode1.GetFolderBranch()) 885 if err != nil { 886 t.Fatalf("Couldn't sync file: %+v", err) 887 } 888 889 rootNode2 := GetRootNodeOrBust(ctx, t, config2, name, tlf.Private) 890 891 kbfsOps2 := config2.KBFSOps() 892 893 // user 2 creates a file 894 _, _, err = kbfsOps2.CreateFile(ctx, rootNode2, testPPS("b"), false, NoExcl) 895 if err != nil { 896 t.Fatalf("Couldn't create file: %+v", err) 897 } 898 err = kbfsOps2.SyncAll(ctx, rootNode2.GetFolderBranch()) 899 if err != nil { 900 t.Fatalf("Couldn't sync file: %+v", err) 901 } 902 903 config2Dev2 := ConfigAsUser(config1, u2) 904 defer CheckConfigAndShutdown(ctx, t, config2Dev2) 905 906 // Now give u2 a new device. The configs don't share a Keybase 907 // Daemon so we have to do it in all places. 908 AddDeviceForLocalUserOrBust(t, config1, uid2) 909 AddDeviceForLocalUserOrBust(t, config2, uid2) 910 devIndex := AddDeviceForLocalUserOrBust(t, config2Dev2, uid2) 911 SwitchDeviceForLocalUserOrBust(t, config2Dev2, devIndex) 912 913 // user 2 should be unable to read the data now since its device 914 // wasn't registered when the folder was originally created. 915 _, err = GetRootNodeForTest(ctx, config2Dev2, name, tlf.Private) 916 if _, ok := err.(NeedSelfRekeyError); !ok { 917 t.Fatalf("Got unexpected error when reading with new key: %+v", err) 918 } 919 920 // GetTLFCryptKeys needs to return the same error. 921 rmd, err := config1.MDOps().GetForTLF(ctx, rootNode1.GetFolderBranch().Tlf, nil) 922 if err != nil { 923 t.Fatalf("Couldn't get latest md: %+v", err) 924 } 925 _, _, err = config2Dev2.KBFSOps().GetTLFCryptKeys(ctx, rmd.GetTlfHandle()) 926 if _, ok := err.(NeedSelfRekeyError); !ok { 927 t.Fatalf("Got unexpected error when reading with new key: %+v", err) 928 } 929 930 // Set the KBPKI so we can count the identify calls 931 countKBPKI := &identifyCountingKBPKI{ 932 KBPKI: config1.KBPKI(), 933 } 934 config1.SetKBPKI(countKBPKI) 935 // Force the FBO to forget about its previous identify, so that we 936 // can make sure the rekey doesn't trigger a full identify. 937 kbfsOps1.(*KBFSOpsStandard).getOpsNoAdd( 938 ctx, rootNode1.GetFolderBranch()).identifyDone = false 939 940 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 941 kbfsOps1, rootNode1.GetFolderBranch().Tlf) 942 if err != nil { 943 t.Fatalf("Couldn't rekey: %+v", err) 944 } 945 946 // Only u2 should be identified as part of the rekey. 947 if g, e := countKBPKI.getIdentifyCalls(), 1; g != e { 948 t.Errorf("Expected %d identify calls, but got %d", e, g) 949 } 950 951 // u2 syncs after the rekey 952 if err := kbfsOps2.SyncFromServer(ctx, 953 rootNode2.GetFolderBranch(), nil); err != nil { 954 t.Fatalf("Couldn't sync from server: %+v", err) 955 } 956 957 // user 2 creates another file 958 _, _, err = kbfsOps2.CreateFile(ctx, rootNode2, testPPS("c"), false, NoExcl) 959 if err != nil { 960 t.Fatalf("Couldn't create file: %+v", err) 961 } 962 err = kbfsOps2.SyncAll(ctx, rootNode2.GetFolderBranch()) 963 if err != nil { 964 t.Fatalf("Couldn't sync file: %+v", err) 965 } 966 967 // add a third device for user 2 968 config2Dev3 := ConfigAsUser(config1, u2) 969 defer CheckConfigAndShutdown(ctx, t, config2Dev3) 970 defer config2Dev3.SetKeyCache(NewKeyCacheStandard(5000)) 971 AddDeviceForLocalUserOrBust(t, config1, uid2) 972 AddDeviceForLocalUserOrBust(t, config2, uid2) 973 AddDeviceForLocalUserOrBust(t, config2Dev2, uid2) 974 devIndex = AddDeviceForLocalUserOrBust(t, config2Dev3, uid2) 975 SwitchDeviceForLocalUserOrBust(t, config2Dev3, devIndex) 976 977 // Now revoke the original user 2 device (the last writer) 978 clock.Add(1 * time.Minute) 979 RevokeDeviceForLocalUserOrBust(t, config1, uid2, 0) 980 RevokeDeviceForLocalUserOrBust(t, config2Dev2, uid2, 0) 981 RevokeDeviceForLocalUserOrBust(t, config2Dev3, uid2, 0) 982 983 SetGlobalMerkleRootForTestOrBust( 984 t, config1, keybase1.MerkleRootV2{}, clock.Now()) 985 SetGlobalMerkleRootForTestOrBust( 986 t, config2Dev2, keybase1.MerkleRootV2{}, clock.Now()) 987 SetGlobalMerkleRootForTestOrBust( 988 t, config2Dev3, keybase1.MerkleRootV2{}, clock.Now()) 989 SetKbfsMerkleRootForTestOrBust( 990 t, config1, keybase1.MerkleTreeID_KBFS_PRIVATE, &kbfsmd.MerkleRoot{ 991 Timestamp: clock.Now().Unix(), 992 }) 993 994 // First request a rekey from the new device, which will only be 995 // able to set the rekey bit (copying the root MD). 996 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 997 config2Dev3.KBFSOps(), rootNode1.GetFolderBranch().Tlf) 998 if err != nil { 999 t.Fatalf("Couldn't rekey: %+v", err) 1000 } 1001 1002 err = kbfsOps1.SyncFromServer(ctx, 1003 rootNode1.GetFolderBranch(), nil) 1004 if err != nil { 1005 t.Fatalf("Couldn't sync from server: %+v", err) 1006 } 1007 1008 // rekey again 1009 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 1010 kbfsOps1, rootNode1.GetFolderBranch().Tlf) 1011 if err != nil { 1012 t.Fatalf("Couldn't rekey: %+v", err) 1013 } 1014 1015 // Only u2 should be identified again as part of the rekey. 1016 if g, e := countKBPKI.getIdentifyCalls(), 2; g != e { 1017 t.Errorf("Expected %d identify calls, but got %d", e, g) 1018 } 1019 1020 // force re-encryption of the root dir 1021 _, _, err = kbfsOps1.CreateFile(ctx, rootNode1, testPPS("d"), false, NoExcl) 1022 if err != nil { 1023 t.Fatalf("Couldn't create file: %+v", err) 1024 } 1025 err = kbfsOps1.SyncAll(ctx, rootNode1.GetFolderBranch()) 1026 if err != nil { 1027 t.Fatalf("Couldn't sync file: %+v", err) 1028 } 1029 1030 // this device should be able to read now 1031 root2Dev2 := GetRootNodeOrBust(ctx, t, config2Dev2, name, tlf.Private) 1032 1033 kbfsOps2Dev2 := config2Dev2.KBFSOps() 1034 err = kbfsOps2Dev2.SyncFromServer(ctx, 1035 root2Dev2.GetFolderBranch(), nil) 1036 if err != nil { 1037 t.Fatalf("Couldn't sync from server: %+v", err) 1038 } 1039 1040 // device 2 should still work 1041 rootNode2Dev2 := GetRootNodeOrBust(ctx, t, config2Dev2, name, tlf.Private) 1042 1043 children, err := kbfsOps2Dev2.GetDirChildren(ctx, rootNode2Dev2) 1044 require.NoError(t, err) 1045 if _, ok := children[rootNode2Dev2.ChildName("d")]; !ok { 1046 t.Fatalf("Device 2 couldn't see the new dir entry") 1047 } 1048 1049 // But device 1 should now fail to see any updates. TODO: when a 1050 // device sees it has been revoked from the TLF, we should delete 1051 // all its cached data and refuse to serve any more. (However, in 1052 // production the device's session would likely be revoked, 1053 // probably leading to NoCurrentSession errors anyway.) 1054 err = kbfsOps2.SyncFromServer(ctx, 1055 rootNode2.GetFolderBranch(), nil) 1056 if err == nil { 1057 // This is not expected to succeed; the node will be unable to 1058 // deserialize the private MD. 1059 t.Fatalf("Unexpectedly could sync from server") 1060 } 1061 // Should still be seeing the old children, since the updates from 1062 // the latest revision were never applied. 1063 children, err = kbfsOps2.GetDirChildren(ctx, rootNode2) 1064 require.NoError(t, err) 1065 if _, ok := children[rootNode2.ChildName("d")]; ok { 1066 t.Fatalf("Found c unexpectedly: %v", children) 1067 } 1068 1069 // meanwhile, device 3 should be able to read both the new and the 1070 // old files 1071 kbfsOps3 := config2Dev3.KBFSOps() 1072 err = kbfsOps3.SyncFromServer( 1073 ctx, rootNode2.GetFolderBranch(), nil) 1074 require.NoError(t, err) 1075 rootNode2Dev3 := GetRootNodeOrBust(ctx, t, config2Dev3, name, tlf.Private) 1076 1077 kbfsOps2Dev3 := config2Dev3.KBFSOps() 1078 aNode, _, err := kbfsOps2Dev3.Lookup(ctx, rootNode2Dev3, testPPS("a")) 1079 if err != nil { 1080 t.Fatalf("Device 3 couldn't lookup a: %+v", err) 1081 } 1082 1083 buf := []byte{0} 1084 _, err = kbfsOps2Dev3.Read(ctx, aNode, buf, 0) 1085 if err != nil { 1086 t.Fatalf("Device 3 couldn't read a: %+v", err) 1087 } 1088 1089 bNode, _, err := kbfsOps2Dev3.Lookup(ctx, rootNode2Dev3, testPPS("b")) 1090 if err != nil { 1091 t.Fatalf("Device 3 couldn't lookup b: %+v", err) 1092 } 1093 1094 _, err = kbfsOps2Dev3.Read(ctx, bNode, buf, 0) 1095 if err != nil { 1096 t.Fatalf("Device 3 couldn't read b: %+v", err) 1097 } 1098 1099 // Make sure the server-side keys for the revoked device are gone 1100 // for all keygens. 1101 rmd, err = config1.MDOps().GetForTLF(ctx, rootNode1.GetFolderBranch().Tlf, nil) 1102 if err != nil { 1103 t.Fatalf("Couldn't get latest md: %+v", err) 1104 } 1105 currKeyGen := rmd.LatestKeyGeneration() 1106 // clear the key cache 1107 config2.SetKeyCache(NewKeyCacheStandard(5000)) 1108 km2, ok := config2.KeyManager().(*KeyManagerStandard) 1109 if !ok { 1110 t.Fatal("Wrong kind of key manager for config2") 1111 } 1112 for keyGen := kbfsmd.FirstValidKeyGen; keyGen <= currKeyGen; keyGen++ { 1113 _, err = km2.getTLFCryptKeyUsingCurrentDevice(ctx, rmd.ReadOnly(), keyGen, true) 1114 if err == nil { 1115 t.Errorf("User 2 could still fetch a key for keygen %d", keyGen) 1116 } 1117 } 1118 } 1119 1120 func testKeyManagerRekeyAddWriterAndReaderDevice(t *testing.T, ver kbfsmd.MetadataVer) { 1121 var u1, u2, u3 kbname.NormalizedUsername = "u1", "u2", "u3" 1122 config1, _, ctx, cancel := kbfsOpsConcurInit(t, u1, u2, u3) 1123 defer kbfsConcurTestShutdown(ctx, t, config1, cancel) 1124 1125 config1.SetMetadataVersion(ver) 1126 1127 // Revoke user 3's device for now, to test the "other" rekey error. 1128 _, id3, err := config1.KBPKI().Resolve( 1129 ctx, u3.String(), keybase1.OfflineAvailability_NONE) 1130 if err != nil { 1131 t.Fatalf("Couldn't resolve u3: %+v", err) 1132 } 1133 uid3, err := id3.AsUser() 1134 require.NoError(t, err) 1135 1136 RevokeDeviceForLocalUserOrBust(t, config1, uid3, 0) 1137 1138 config2 := ConfigAsUser(config1, u2) 1139 defer CheckConfigAndShutdown(ctx, t, config2) 1140 session2, err := config2.KBPKI().GetCurrentSession(ctx) 1141 if err != nil { 1142 t.Fatal(err) 1143 } 1144 uid2 := session2.UID 1145 1146 // Create a shared folder 1147 name := u1.String() + "," + u2.String() + tlf.ReaderSep + u3.String() 1148 1149 rootNode1 := GetRootNodeOrBust(ctx, t, config1, name, tlf.Private) 1150 1151 kbfsOps1 := config1.KBFSOps() 1152 1153 // user 1 creates a file 1154 _, _, err = kbfsOps1.CreateFile(ctx, rootNode1, testPPS("a"), false, NoExcl) 1155 if err != nil { 1156 t.Fatalf("Couldn't create file: %+v", err) 1157 } 1158 err = kbfsOps1.SyncAll(ctx, rootNode1.GetFolderBranch()) 1159 if err != nil { 1160 t.Fatalf("Couldn't sync file: %+v", err) 1161 } 1162 err = kbfsOps1.SyncFromServer(ctx, rootNode1.GetFolderBranch(), nil) 1163 if err != nil { 1164 t.Fatalf("Couldn't sync from server: %+v", err) 1165 } 1166 1167 config2Dev2 := ConfigAsUser(config1, u2) 1168 defer CheckConfigAndShutdown(ctx, t, config2Dev2) 1169 1170 config3 := ConfigAsUser(config1, u3) 1171 defer CheckConfigAndShutdown(ctx, t, config3) 1172 1173 // Now give u2 and u3 new devices. The configs don't share a 1174 // Keybase Daemon so we have to do it in all places. 1175 AddDeviceForLocalUserOrBust(t, config1, uid2) 1176 AddDeviceForLocalUserOrBust(t, config2, uid2) 1177 devIndex := AddDeviceForLocalUserOrBust(t, config2Dev2, uid2) 1178 SwitchDeviceForLocalUserOrBust(t, config2Dev2, devIndex) 1179 AddDeviceForLocalUserOrBust(t, config1, uid3) 1180 AddDeviceForLocalUserOrBust(t, config2, uid3) 1181 devIndex = AddDeviceForLocalUserOrBust(t, config3, uid3) 1182 t.Logf("Switching to device %d", devIndex) 1183 SwitchDeviceForLocalUserOrBust(t, config3, devIndex) 1184 1185 // Users 2 and 3 should be unable to read the data now since its 1186 // device wasn't registered when the folder was originally 1187 // created. 1188 _, err = GetRootNodeForTest(ctx, config2Dev2, name, tlf.Private) 1189 if _, ok := err.(NeedSelfRekeyError); !ok { 1190 t.Fatalf("Got unexpected error when reading with new key: %+v", err) 1191 } 1192 _, err = GetRootNodeForTest(ctx, config3, name, tlf.Private) 1193 if _, ok := err.(NeedOtherRekeyError); !ok { 1194 t.Fatalf("Got unexpected error when reading with new key: %+v", err) 1195 } 1196 1197 // Set the KBPKI so we can count the identify calls 1198 countKBPKI := &identifyCountingKBPKI{ 1199 KBPKI: config1.KBPKI(), 1200 } 1201 config1.SetKBPKI(countKBPKI) 1202 // Force the FBO to forget about its previous identify, so that we 1203 // can make sure the rekey doesn't trigger a full identify. 1204 kbfsOps1.(*KBFSOpsStandard).getOpsNoAdd( 1205 ctx, rootNode1.GetFolderBranch()).identifyDone = false 1206 1207 // now user 1 should rekey 1208 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 1209 kbfsOps1, rootNode1.GetFolderBranch().Tlf) 1210 if err != nil { 1211 t.Fatalf("Couldn't rekey: %+v", err) 1212 } 1213 1214 // u2 and u3 should be identified as part of the rekey. 1215 if g, e := countKBPKI.getIdentifyCalls(), 2; g != e { 1216 t.Errorf("Expected %d identify calls, but got %d", e, g) 1217 } 1218 1219 // The new devices should be able to read now. 1220 _, err = GetRootNodeForTest(ctx, config2Dev2, name, tlf.Private) 1221 if err != nil { 1222 t.Fatalf("Got unexpected error after rekey: %+v", err) 1223 } 1224 1225 _ = GetRootNodeOrBust(ctx, t, config3, name, tlf.Private) 1226 } 1227 1228 func testKeyManagerSelfRekeyAcrossDevices(t *testing.T, ver kbfsmd.MetadataVer) { 1229 var u1, u2 kbname.NormalizedUsername = "u1", "u2" 1230 config1, _, ctx, cancel := kbfsOpsConcurInit(t, u1, u2) 1231 defer kbfsConcurTestShutdown(ctx, t, config1, cancel) 1232 1233 config1.SetMetadataVersion(ver) 1234 1235 config2 := ConfigAsUser(config1, u2) 1236 defer CheckConfigAndShutdown(ctx, t, config2) 1237 session2, err := config2.KBPKI().GetCurrentSession(ctx) 1238 if err != nil { 1239 t.Fatal(err) 1240 } 1241 uid2 := session2.UID 1242 1243 t.Log("Create a shared folder") 1244 name := u1.String() + "," + u2.String() 1245 1246 rootNode1 := GetRootNodeOrBust(ctx, t, config1, name, tlf.Private) 1247 1248 kbfsOps1 := config1.KBFSOps() 1249 1250 t.Log("User 1 creates a file") 1251 _, _, err = kbfsOps1.CreateFile(ctx, rootNode1, testPPS("a"), false, NoExcl) 1252 if err != nil { 1253 t.Fatalf("Couldn't create file: %+v", err) 1254 } 1255 err = kbfsOps1.SyncAll(ctx, rootNode1.GetFolderBranch()) 1256 if err != nil { 1257 t.Fatalf("Couldn't sync file: %+v", err) 1258 } 1259 1260 t.Log("User 2 adds a device") 1261 // The configs don't share a Keybase Daemon so we have to do it in all 1262 // places. 1263 AddDeviceForLocalUserOrBust(t, config1, uid2) 1264 devIndex := AddDeviceForLocalUserOrBust(t, config2, uid2) 1265 1266 config2Dev2 := ConfigAsUser(config2, u2) 1267 defer CheckConfigAndShutdown(ctx, t, config2Dev2) 1268 SwitchDeviceForLocalUserOrBust(t, config2Dev2, devIndex) 1269 1270 t.Log("Check that user 2 device 2 is unable to read the file") 1271 // user 2 device 2 should be unable to read the data now since its device 1272 // wasn't registered when the folder was originally created. 1273 _, err = GetRootNodeForTest(ctx, config2Dev2, name, tlf.Private) 1274 if _, ok := err.(NeedSelfRekeyError); !ok { 1275 t.Fatalf("Got unexpected error when reading with new key: %+v", err) 1276 } 1277 1278 t.Log("User 2 rekeys from device 1") 1279 root2dev1 := GetRootNodeOrBust(ctx, t, config2, name, tlf.Private) 1280 1281 kbfsOps2 := config2.KBFSOps() 1282 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 1283 kbfsOps2, root2dev1.GetFolderBranch().Tlf) 1284 if err != nil { 1285 t.Fatalf("Couldn't rekey: %+v", err) 1286 } 1287 1288 t.Log("User 2 device 2 should be able to read now") 1289 root2dev2 := GetRootNodeOrBust(ctx, t, config2Dev2, name, tlf.Private) 1290 1291 t.Log("User 2 device 2 reads user 1's file") 1292 kbfsOps2Dev2 := config2Dev2.KBFSOps() 1293 children2, err := kbfsOps2Dev2.GetDirChildren(ctx, root2dev2) 1294 require.NoError(t, err) 1295 if _, ok := children2[root2dev2.ChildName("a")]; !ok { 1296 t.Fatalf("Device 2 couldn't see user 1's dir entry") 1297 } 1298 1299 t.Log("User 2 device 2 creates a file") 1300 _, _, err = kbfsOps2Dev2.CreateFile( 1301 ctx, root2dev2, testPPS("b"), false, NoExcl) 1302 if err != nil { 1303 t.Fatalf("Couldn't create file: %+v", err) 1304 } 1305 err = kbfsOps2Dev2.SyncAll(ctx, root2dev2.GetFolderBranch()) 1306 if err != nil { 1307 t.Fatalf("Couldn't sync file: %+v", err) 1308 } 1309 1310 t.Log("User 1 syncs from the server") 1311 err = kbfsOps1.SyncFromServer(ctx, 1312 rootNode1.GetFolderBranch(), nil) 1313 if err != nil { 1314 t.Fatalf("Couldn't sync from server: %+v", err) 1315 } 1316 1317 t.Log("User 1 should be able to read the file that user 2 device 2 created") 1318 children1, err := kbfsOps1.GetDirChildren(ctx, rootNode1) 1319 require.NoError(t, err) 1320 if _, ok := children1[rootNode1.ChildName("b")]; !ok { 1321 t.Fatalf("Device 1 couldn't see the new dir entry") 1322 } 1323 } 1324 1325 func testKeyManagerReaderRekey(t *testing.T, ver kbfsmd.MetadataVer) { 1326 var u1, u2 kbname.NormalizedUsername = "u1", "u2" 1327 config1, _, ctx, cancel := kbfsOpsConcurInit(t, u1, u2) 1328 defer kbfsConcurTestShutdown(ctx, t, config1, cancel) 1329 session1, err := config1.KBPKI().GetCurrentSession(ctx) 1330 require.NoError(t, err) 1331 1332 config1.SetMetadataVersion(ver) 1333 1334 config2 := ConfigAsUser(config1, u2) 1335 defer CheckConfigAndShutdown(ctx, t, config2) 1336 session2, err := config2.KBPKI().GetCurrentSession(ctx) 1337 if err != nil { 1338 t.Fatal(err) 1339 } 1340 uid2 := session2.UID 1341 1342 t.Log("Create a shared folder") 1343 name := u1.String() + tlf.ReaderSep + u2.String() 1344 1345 rootNode1 := GetRootNodeOrBust(ctx, t, config1, name, tlf.Private) 1346 1347 kbfsOps1 := config1.KBFSOps() 1348 1349 t.Log("User 1 creates a file") 1350 _, _, err = kbfsOps1.CreateFile(ctx, rootNode1, testPPS("a"), false, NoExcl) 1351 if err != nil { 1352 t.Fatalf("Couldn't create file: %+v", err) 1353 } 1354 err = kbfsOps1.SyncAll(ctx, rootNode1.GetFolderBranch()) 1355 if err != nil { 1356 t.Fatalf("Couldn't sync file: %+v", err) 1357 } 1358 1359 t.Log("User 1 adds a device") 1360 // The configs don't share a Keybase Daemon so we have to do it in all 1361 // places. 1362 AddDeviceForLocalUserOrBust(t, config1, session1.UID) 1363 devIndex := AddDeviceForLocalUserOrBust(t, config2, session1.UID) 1364 1365 config1Dev2 := ConfigAsUser(config2, u1) 1366 defer CheckConfigAndShutdown(ctx, t, config1Dev2) 1367 SwitchDeviceForLocalUserOrBust(t, config1Dev2, devIndex) 1368 1369 t.Log("User 2 adds a device") 1370 // The configs don't share a Keybase Daemon so we have to do it in all 1371 // places. 1372 AddDeviceForLocalUserOrBust(t, config1, uid2) 1373 AddDeviceForLocalUserOrBust(t, config1Dev2, uid2) 1374 devIndex = AddDeviceForLocalUserOrBust(t, config2, uid2) 1375 1376 config2Dev2 := ConfigAsUser(config2, u2) 1377 defer CheckConfigAndShutdown(ctx, t, config2Dev2) 1378 SwitchDeviceForLocalUserOrBust(t, config2Dev2, devIndex) 1379 1380 t.Log("Check that user 2 device 2 is unable to read the file") 1381 // user 2 device 2 should be unable to read the data now since its device 1382 // wasn't registered when the folder was originally created. 1383 kbfsOps2Dev2 := config2Dev2.KBFSOps() 1384 _, err = GetRootNodeForTest(ctx, config2Dev2, name, tlf.Private) 1385 if _, ok := err.(NeedSelfRekeyError); !ok { 1386 t.Fatalf("Got unexpected error when reading with new key: %+v", err) 1387 } 1388 1389 t.Log("User 2 rekeys from device 1") 1390 root2dev1 := GetRootNodeOrBust(ctx, t, config2, name, tlf.Private) 1391 1392 kbfsOps2 := config2.KBFSOps() 1393 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 1394 kbfsOps2, root2dev1.GetFolderBranch().Tlf) 1395 if err != nil { 1396 t.Fatalf("Expected reader rekey to partially complete. Actual error: %#v", err) 1397 } 1398 1399 t.Log("User 2 device 2 should be able to read now") 1400 root2dev2 := GetRootNodeOrBust(ctx, t, config2Dev2, name, tlf.Private) 1401 1402 t.Log("User 1 device 2 should still be unable to read") 1403 _, err = GetRootNodeForTest(ctx, config1Dev2, name, tlf.Private) 1404 if _, ok := err.(NeedSelfRekeyError); !ok { 1405 t.Fatalf("Got unexpected error when reading with new key: %+v", err) 1406 } 1407 1408 t.Log("User 2 device 2 reads user 1's file") 1409 children2, err := kbfsOps2Dev2.GetDirChildren(ctx, root2dev2) 1410 require.NoError(t, err) 1411 if _, ok := children2[root2dev2.ChildName("a")]; !ok { 1412 t.Fatalf("Device 2 couldn't see user 1's dir entry") 1413 } 1414 } 1415 1416 func testKeyManagerReaderRekeyAndRevoke(t *testing.T, ver kbfsmd.MetadataVer) { 1417 var u1, u2 kbname.NormalizedUsername = "u1", "u2" 1418 config1, _, ctx, cancel := kbfsOpsConcurInit(t, u1, u2) 1419 defer kbfsConcurTestShutdown(ctx, t, config1, cancel) 1420 clock := clocktest.NewTestClockNow() 1421 config1.SetClock(clock) 1422 1423 config1.SetMetadataVersion(ver) 1424 1425 config2 := ConfigAsUser(config1, u2) 1426 defer CheckConfigAndShutdown(ctx, t, config2) 1427 session2, err := config2.KBPKI().GetCurrentSession(ctx) 1428 if err != nil { 1429 t.Fatal(err) 1430 } 1431 uid2 := session2.UID 1432 1433 // The reader has a second device at the start. 1434 AddDeviceForLocalUserOrBust(t, config1, uid2) 1435 devIndex := AddDeviceForLocalUserOrBust(t, config2, uid2) 1436 config2Dev2 := ConfigAsUser(config2, u2) 1437 defer CheckConfigAndShutdown(ctx, t, config2Dev2) 1438 SwitchDeviceForLocalUserOrBust(t, config2Dev2, devIndex) 1439 1440 t.Log("Create a shared folder") 1441 name := u1.String() + tlf.ReaderSep + u2.String() 1442 1443 rootNode1 := GetRootNodeOrBust(ctx, t, config1, name, tlf.Private) 1444 1445 kbfsOps1 := config1.KBFSOps() 1446 1447 t.Log("User 1 creates a file") 1448 _, _, err = kbfsOps1.CreateFile(ctx, rootNode1, testPPS("a"), false, NoExcl) 1449 if err != nil { 1450 t.Fatalf("Couldn't create file: %+v", err) 1451 } 1452 err = kbfsOps1.SyncAll(ctx, rootNode1.GetFolderBranch()) 1453 if err != nil { 1454 t.Fatalf("Couldn't sync file: %+v", err) 1455 } 1456 1457 t.Log("User 2 adds a device") 1458 // The configs don't share a Keybase Daemon so we have to do it in all 1459 // places. 1460 AddDeviceForLocalUserOrBust(t, config1, uid2) 1461 AddDeviceForLocalUserOrBust(t, config2, uid2) 1462 devIndex = AddDeviceForLocalUserOrBust(t, config2Dev2, uid2) 1463 config2Dev3 := ConfigAsUser(config2, u2) 1464 defer CheckConfigAndShutdown(ctx, t, config2Dev3) 1465 SwitchDeviceForLocalUserOrBust(t, config2Dev3, devIndex) 1466 1467 // Revoke the original user 2 device 1468 clock.Add(1 * time.Minute) 1469 RevokeDeviceForLocalUserOrBust(t, config1, uid2, 0) 1470 RevokeDeviceForLocalUserOrBust(t, config2Dev2, uid2, 0) 1471 RevokeDeviceForLocalUserOrBust(t, config2Dev3, uid2, 0) 1472 1473 t.Log("Check that user 2 device 3 is unable to read the file") 1474 // user 2 device 3 should be unable to read the data now since its device 1475 // wasn't registered when the folder was originally created. 1476 _, err = GetRootNodeForTest(ctx, config2Dev3, name, tlf.Private) 1477 if _, ok := err.(NeedSelfRekeyError); !ok { 1478 t.Fatalf("Got unexpected error when reading with new key: %+v", err) 1479 } 1480 1481 t.Log("User 2 rekeys from device 2") 1482 root2Dev2 := GetRootNodeOrBust(ctx, t, config2Dev2, name, tlf.Private) 1483 kbfsOps2Dev2 := config2Dev2.KBFSOps() 1484 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 1485 kbfsOps2Dev2, root2Dev2.GetFolderBranch().Tlf) 1486 if err != nil { 1487 t.Fatalf("Expected reader rekey to partially complete. "+ 1488 "Actual error: %#v", err) 1489 } 1490 1491 t.Log("User 2 device 3 should be able to read now") 1492 GetRootNodeOrBust(ctx, t, config2Dev3, name, tlf.Private) 1493 1494 // A second rekey by the same reader shouldn't change the 1495 // revision, since the rekey bit is already set, even though a 1496 // rekey is still needed (due to the revoke, which has to be 1497 // rekeyed by a writer). 1498 ops := getOps(config2Dev2, root2Dev2.GetFolderBranch().Tlf) 1499 rev1 := ops.head.Revision() 1500 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 1501 kbfsOps2Dev2, root2Dev2.GetFolderBranch().Tlf) 1502 if err != nil { 1503 t.Fatalf("Expected reader rekey to partially complete. "+ 1504 "Actual error: %#v", err) 1505 } 1506 rev2 := ops.head.Revision() 1507 if rev1 != rev2 { 1508 t.Fatalf("Reader rekey made two incomplete rekeys in a row.") 1509 } 1510 } 1511 1512 func keyManagerTestSimulateSelfRekeyBit( 1513 ctx context.Context, t *testing.T, config Config, tlfID tlf.ID) { 1514 // Simulate the mdserver sending back this node's own rekey 1515 // request. This shouldn't increase the MD version. Since this 1516 // doesn't kick off a rekey request, we don't need to wait for the 1517 // whole rekey to finish; we just wait for the event to be 1518 // processed. 1519 rekeyWaiter := make(chan struct{}) 1520 ops := getOps(config, tlfID) 1521 rev1 := ops.head.Revision() 1522 ops.rekeyFSM.listenOnEvent(rekeyRequestEvent, func(e RekeyEvent) { 1523 close(rekeyWaiter) 1524 }, false) 1525 ops.rekeyFSM.Event(newRekeyRequestEventWithContext(ctx)) 1526 <-rekeyWaiter 1527 rev2 := ops.head.Revision() 1528 1529 if rev1 != rev2 { 1530 t.Errorf("Revision changed after second rekey: %v vs %v", rev1, rev2) 1531 } 1532 1533 // Make sure just the rekey bit is set 1534 if !ops.head.IsRekeySet() { 1535 t.Fatalf("Couldn't set rekey bit") 1536 } 1537 } 1538 1539 // This tests 2 variations of the situation where clients w/o the folder key set the rekey bit. 1540 // In one case the client is a writer and in the other a reader. They both blindly copy the existing 1541 // metadata and simply set the rekey bit. Then another participant rekeys the folder and they try to read. 1542 1543 func testKeyManagerRekeyBit(t *testing.T, ver kbfsmd.MetadataVer) { 1544 var u1, u2, u3 kbname.NormalizedUsername = "u1", "u2", "u3" 1545 config1, _, ctx, cancel := kbfsOpsConcurInit(t, u1, u2, u3) 1546 doShutdown1 := true 1547 defer func() { 1548 if doShutdown1 { 1549 kbfsConcurTestShutdown(ctx, t, config1, cancel) 1550 } 1551 }() 1552 1553 config1.SetMetadataVersion(ver) 1554 1555 config2 := ConfigAsUser(config1, u2) 1556 defer CheckConfigAndShutdown(ctx, t, config2) 1557 session2, err := config2.KBPKI().GetCurrentSession(ctx) 1558 if err != nil { 1559 t.Fatal(err) 1560 } 1561 uid2 := session2.UID 1562 1563 config2.MDServer().DisableRekeyUpdatesForTesting() 1564 1565 config3 := ConfigAsUser(config1, u3) 1566 defer CheckConfigAndShutdown(ctx, t, config3) 1567 session3, err := config3.KBPKI().GetCurrentSession(ctx) 1568 if err != nil { 1569 t.Fatal(err) 1570 } 1571 uid3 := session3.UID 1572 1573 config3.MDServer().DisableRekeyUpdatesForTesting() 1574 1575 // 2 writers 1 reader 1576 name := u1.String() + "," + u2.String() + "#" + u3.String() 1577 1578 rootNode1 := GetRootNodeOrBust(ctx, t, config1, name, tlf.Private) 1579 1580 kbfsOps1 := config1.KBFSOps() 1581 1582 // user 1 creates a file 1583 _, _, err = kbfsOps1.CreateFile(ctx, rootNode1, testPPS("a"), false, NoExcl) 1584 if err != nil { 1585 t.Fatalf("Couldn't create file: %+v", err) 1586 } 1587 err = kbfsOps1.SyncAll(ctx, rootNode1.GetFolderBranch()) 1588 if err != nil { 1589 t.Fatalf("Couldn't sync file: %+v", err) 1590 } 1591 1592 config2Dev2 := ConfigAsUser(config1, u2) 1593 // we don't check the config because this device can't read all of the md blocks. 1594 defer func() { _ = config2Dev2.Shutdown(ctx) }() 1595 config2Dev2.MDServer().DisableRekeyUpdatesForTesting() 1596 1597 // Now give u2 a new device. The configs don't share a Keybase 1598 // Daemon so we have to do it in all places. 1599 AddDeviceForLocalUserOrBust(t, config1, uid2) 1600 AddDeviceForLocalUserOrBust(t, config2, uid2) 1601 AddDeviceForLocalUserOrBust(t, config3, uid2) 1602 devIndex := AddDeviceForLocalUserOrBust(t, config2Dev2, uid2) 1603 SwitchDeviceForLocalUserOrBust(t, config2Dev2, devIndex) 1604 1605 // user 2 should be unable to read the data now since its device 1606 // wasn't registered when the folder was originally created. 1607 _, err = GetRootNodeForTest(ctx, config2Dev2, name, tlf.Private) 1608 if _, ok := err.(NeedSelfRekeyError); !ok { 1609 t.Fatalf("Got unexpected error when reading with new key: %+v", err) 1610 } 1611 1612 // now user 2 should set the rekey bit 1613 kbfsOps2Dev2 := config2Dev2.KBFSOps() 1614 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 1615 kbfsOps2Dev2, rootNode1.GetFolderBranch().Tlf) 1616 if err != nil { 1617 t.Fatalf("Couldn't rekey: %+v", err) 1618 } 1619 1620 // Do it again, to simulate the mdserver sending back this node's 1621 // own rekey request. 1622 keyManagerTestSimulateSelfRekeyBit( 1623 ctx, t, config2Dev2, rootNode1.GetFolderBranch().Tlf) 1624 1625 // user 1 syncs from server 1626 err = kbfsOps1.SyncFromServer(ctx, 1627 rootNode1.GetFolderBranch(), nil) 1628 if err != nil { 1629 t.Fatalf("Couldn't sync from server: %+v", err) 1630 } 1631 1632 // user 1 should try to rekey 1633 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 1634 kbfsOps1, rootNode1.GetFolderBranch().Tlf) 1635 if err != nil { 1636 t.Fatalf("Couldn't rekey: %+v", err) 1637 } 1638 1639 // user 2 syncs from server 1640 err = kbfsOps2Dev2.SyncFromServer(ctx, 1641 rootNode1.GetFolderBranch(), nil) 1642 if err != nil { 1643 t.Fatalf("Couldn't sync from server: %+v", err) 1644 } 1645 1646 // this device should be able to read now 1647 rootNode2Dev2 := GetRootNodeOrBust(ctx, t, config2Dev2, name, tlf.Private) 1648 1649 // look for the file 1650 aNode, _, err := kbfsOps2Dev2.Lookup(ctx, rootNode2Dev2, testPPS("a")) 1651 if err != nil { 1652 t.Fatalf("Device 2 couldn't lookup a: %+v", err) 1653 } 1654 1655 // read it 1656 buf := []byte{0} 1657 _, err = kbfsOps2Dev2.Read(ctx, aNode, buf, 0) 1658 if err != nil { 1659 t.Fatalf("Device 2 couldn't read a: %+v", err) 1660 } 1661 1662 config3Dev2 := ConfigAsUser(config1, u3) 1663 // we don't check the config because this device can't read all of the md blocks. 1664 defer func() { _ = config3Dev2.Shutdown(ctx) }() 1665 config3Dev2.MDServer().DisableRekeyUpdatesForTesting() 1666 1667 // Now give u3 a new device. 1668 AddDeviceForLocalUserOrBust(t, config1, uid3) 1669 AddDeviceForLocalUserOrBust(t, config2, uid3) 1670 AddDeviceForLocalUserOrBust(t, config2Dev2, uid3) 1671 AddDeviceForLocalUserOrBust(t, config3, uid3) 1672 devIndex = AddDeviceForLocalUserOrBust(t, config3Dev2, uid3) 1673 SwitchDeviceForLocalUserOrBust(t, config3Dev2, devIndex) 1674 1675 // user 3 dev 2 should be unable to read the data now since its device 1676 // wasn't registered when the folder was originally created. 1677 _, err = GetRootNodeForTest(ctx, config3Dev2, name, tlf.Private) 1678 if _, ok := err.(NeedSelfRekeyError); !ok { 1679 t.Fatalf("Got unexpected error when reading with new key: %+v", err) 1680 } 1681 1682 // now user 3 dev 2 should set the rekey bit 1683 kbfsOps3Dev2 := config3Dev2.KBFSOps() 1684 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 1685 kbfsOps3Dev2, rootNode1.GetFolderBranch().Tlf) 1686 if err != nil { 1687 t.Fatalf("Couldn't rekey: %+v", err) 1688 } 1689 1690 // user 2 dev 2 syncs from server 1691 err = kbfsOps2Dev2.SyncFromServer(ctx, 1692 rootNode1.GetFolderBranch(), nil) 1693 if err != nil { 1694 t.Fatalf("Couldn't sync from server: %+v", err) 1695 } 1696 1697 // user 2 dev 2 should try to rekey 1698 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 1699 kbfsOps2Dev2, rootNode1.GetFolderBranch().Tlf) 1700 if err != nil { 1701 t.Fatalf("Couldn't rekey: %+v", err) 1702 } 1703 1704 // user 3 dev 2 syncs from server 1705 err = kbfsOps3Dev2.SyncFromServer(ctx, 1706 rootNode1.GetFolderBranch(), nil) 1707 if err != nil { 1708 t.Fatalf("Couldn't sync from server: %+v", err) 1709 } 1710 1711 // this device should be able to read now 1712 rootNode3Dev2 := GetRootNodeOrBust(ctx, t, config3Dev2, name, tlf.Private) 1713 1714 // look for the file 1715 a2Node, _, err := kbfsOps3Dev2.Lookup(ctx, rootNode3Dev2, testPPS("a")) 1716 if err != nil { 1717 t.Fatalf("Device 3 couldn't lookup a: %+v", err) 1718 } 1719 1720 // read it 1721 buf = []byte{0} 1722 _, err = kbfsOps3Dev2.Read(ctx, a2Node, buf, 0) 1723 if err != nil { 1724 t.Fatalf("Device 3 couldn't read a: %+v", err) 1725 } 1726 1727 // Explicitly run the checks with config1 before the deferred shutdowns begin. 1728 // This way the shared mdserver hasn't been shutdown. 1729 kbfsConcurTestShutdown(ctx, t, config1, cancel) 1730 doShutdown1 = false 1731 } 1732 1733 // Two devices conflict when revoking a 3rd device. 1734 // Test that after this both can still read the latest version of the folder. 1735 1736 func testKeyManagerRekeyAddAndRevokeDeviceWithConflict(t *testing.T, ver kbfsmd.MetadataVer) { 1737 var u1, u2 kbname.NormalizedUsername = "u1", "u2" 1738 config1, _, ctx, cancel := kbfsOpsConcurInit(t, u1, u2) 1739 defer kbfsConcurTestShutdown(ctx, t, config1, cancel) 1740 clock := clocktest.NewTestClockNow() 1741 config1.SetClock(clock) 1742 1743 config1.SetMetadataVersion(ver) 1744 1745 config2 := ConfigAsUser(config1, u2) 1746 defer CheckConfigAndShutdown(ctx, t, config2) 1747 session2, err := config2.KBPKI().GetCurrentSession(ctx) 1748 if err != nil { 1749 t.Fatal(err) 1750 } 1751 uid2 := session2.UID 1752 1753 // create a shared folder 1754 name := u1.String() + "," + u2.String() 1755 1756 rootNode1 := GetRootNodeOrBust(ctx, t, config1, name, tlf.Private) 1757 1758 kbfsOps1 := config1.KBFSOps() 1759 1760 // user 1 creates a file 1761 _, _, err = kbfsOps1.CreateFile(ctx, rootNode1, testPPS("a"), false, NoExcl) 1762 if err != nil { 1763 t.Fatalf("Couldn't create file: %+v", err) 1764 } 1765 err = kbfsOps1.SyncAll(ctx, rootNode1.GetFolderBranch()) 1766 if err != nil { 1767 t.Fatalf("Couldn't sync file: %+v", err) 1768 } 1769 1770 config2Dev2 := ConfigAsUser(config1, u2) 1771 defer CheckConfigAndShutdown(ctx, t, config2Dev2) 1772 1773 // give user 2 a new device 1774 AddDeviceForLocalUserOrBust(t, config1, uid2) 1775 AddDeviceForLocalUserOrBust(t, config2, uid2) 1776 devIndex := AddDeviceForLocalUserOrBust(t, config2Dev2, uid2) 1777 SwitchDeviceForLocalUserOrBust(t, config2Dev2, devIndex) 1778 1779 // user 2 should be unable to read the data now since its device 1780 // wasn't registered when the folder was originally created. 1781 kbfsOps2Dev2 := config2Dev2.KBFSOps() 1782 _, err = GetRootNodeForTest(ctx, config2Dev2, name, tlf.Private) 1783 if _, ok := err.(NeedSelfRekeyError); !ok { 1784 t.Fatalf("Got unexpected error when reading with new key: %+v", err) 1785 } 1786 1787 // now user 1 should rekey 1788 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 1789 kbfsOps1, rootNode1.GetFolderBranch().Tlf) 1790 if err != nil { 1791 t.Fatalf("Couldn't rekey: %+v", err) 1792 } 1793 1794 // this device should be able to read now 1795 root2Dev2 := GetRootNodeOrBust(ctx, t, config2Dev2, name, tlf.Private) 1796 1797 // Now revoke the original user 2 device 1798 clock.Add(1 * time.Minute) 1799 RevokeDeviceForLocalUserOrBust(t, config1, uid2, 0) 1800 RevokeDeviceForLocalUserOrBust(t, config2Dev2, uid2, 0) 1801 1802 // Stall user 1's rekey, to ensure a conflict. 1803 onPutStalledCh, putUnstallCh, putCtx := 1804 StallMDOp(ctx, config1, StallableMDPut, 1) 1805 1806 // Have user 1 also try to rekey but fail due to conflict 1807 errChan := make(chan error, 1) 1808 go func() { 1809 _, err := RequestRekeyAndWaitForOneFinishEvent(putCtx, kbfsOps1, rootNode1.GetFolderBranch().Tlf) 1810 errChan <- err 1811 }() 1812 select { 1813 case <-ctx.Done(): 1814 t.Fatal(ctx.Err()) 1815 case <-onPutStalledCh: 1816 } 1817 1818 // rekey again but with user 2 device 2 1819 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 1820 kbfsOps2Dev2, root2Dev2.GetFolderBranch().Tlf) 1821 if err != nil { 1822 t.Fatalf("Couldn't rekey: %+v", err) 1823 } 1824 1825 // Make sure user 1's rekey failed. 1826 select { 1827 case <-ctx.Done(): 1828 t.Fatal(ctx.Err()) 1829 case putUnstallCh <- struct{}{}: 1830 } 1831 select { 1832 case <-ctx.Done(): 1833 t.Fatal(ctx.Err()) 1834 case err = <-errChan: 1835 } 1836 if _, isConflict := err.(RekeyConflictError); !isConflict { 1837 t.Fatalf("Expected failure due to conflict") 1838 } 1839 1840 err = kbfsOps2Dev2.SyncFromServer(ctx, 1841 root2Dev2.GetFolderBranch(), nil) 1842 if err != nil { 1843 t.Fatalf("Couldn't sync from server: %+v", err) 1844 } 1845 1846 // force re-encryption of the root dir 1847 _, _, err = kbfsOps2Dev2.CreateFile( 1848 ctx, root2Dev2, testPPS("b"), false, NoExcl) 1849 if err != nil { 1850 t.Fatalf("Couldn't create file: %+v", err) 1851 } 1852 err = kbfsOps2Dev2.SyncAll(ctx, root2Dev2.GetFolderBranch()) 1853 if err != nil { 1854 t.Fatalf("Couldn't sync file: %+v", err) 1855 } 1856 1857 // device 1 should still work 1858 err = kbfsOps1.SyncFromServer(ctx, 1859 rootNode1.GetFolderBranch(), nil) 1860 if err != nil { 1861 t.Fatalf("Couldn't sync from server: %+v", err) 1862 } 1863 1864 rootNode1 = GetRootNodeOrBust(ctx, t, config1, name, tlf.Private) 1865 1866 children, err := kbfsOps1.GetDirChildren(ctx, rootNode1) 1867 require.NoError(t, err) 1868 if _, ok := children[rootNode1.ChildName("b")]; !ok { 1869 t.Fatalf("Device 1 couldn't see the new dir entry") 1870 } 1871 } 1872 1873 // cryptoLocalTrapAny traps every DecryptTLFCryptKeyClientHalfAny 1874 // call, and closes the given channel the first time it receives one 1875 // with promptPaper set to true. 1876 type cryptoLocalTrapAny struct { 1877 Crypto 1878 promptPaperChOnce sync.Once 1879 promptPaperCh chan<- struct{} 1880 cryptoToUse Crypto 1881 } 1882 1883 func (clta *cryptoLocalTrapAny) DecryptTLFCryptKeyClientHalfAny( 1884 ctx context.Context, 1885 keys []EncryptedTLFCryptKeyClientAndEphemeral, promptPaper bool) ( 1886 kbfscrypto.TLFCryptKeyClientHalf, int, error) { 1887 if promptPaper { 1888 clta.promptPaperChOnce.Do(func() { 1889 close(clta.promptPaperCh) 1890 }) 1891 } 1892 return clta.cryptoToUse.DecryptTLFCryptKeyClientHalfAny( 1893 ctx, keys, promptPaper) 1894 } 1895 1896 func testKeyManagerRekeyAddDeviceWithPrompt(t *testing.T, ver kbfsmd.MetadataVer) { 1897 var u1, u2 kbname.NormalizedUsername = "u1", "u2" 1898 config1, _, ctx, cancel := kbfsOpsConcurInit(t, u1, u2) 1899 defer kbfsConcurTestShutdown(ctx, t, config1, cancel) 1900 1901 config1.SetMetadataVersion(ver) 1902 1903 config2 := ConfigAsUser(config1, u2) 1904 defer CheckConfigAndShutdown(ctx, t, config2) 1905 session2, err := config2.KBPKI().GetCurrentSession(ctx) 1906 if err != nil { 1907 t.Fatal(err) 1908 } 1909 uid2 := session2.UID 1910 1911 // Create a shared folder 1912 name := u1.String() + "," + u2.String() 1913 1914 rootNode1 := GetRootNodeOrBust(ctx, t, config1, name, tlf.Private) 1915 1916 kbfsOps1 := config1.KBFSOps() 1917 1918 // user 1 creates a file 1919 _, _, err = kbfsOps1.CreateFile(ctx, rootNode1, testPPS("a"), false, NoExcl) 1920 if err != nil { 1921 t.Fatalf("Couldn't create file: %+v", err) 1922 } 1923 err = kbfsOps1.SyncAll(ctx, rootNode1.GetFolderBranch()) 1924 if err != nil { 1925 t.Fatalf("Couldn't sync file: %+v", err) 1926 } 1927 1928 config2Dev2 := ConfigAsUser(config1, u2) 1929 defer CheckConfigAndShutdown(ctx, t, config2Dev2) 1930 1931 config2Dev2.SetKeyCache(&dummyNoKeyCache{}) 1932 1933 // Now give u2 a new device. The configs don't share a Keybase 1934 // Daemon so we have to do it in all places. 1935 AddDeviceForLocalUserOrBust(t, config1, uid2) 1936 AddDeviceForLocalUserOrBust(t, config2, uid2) 1937 devIndex := AddDeviceForLocalUserOrBust(t, config2Dev2, uid2) 1938 SwitchDeviceForLocalUserOrBust(t, config2Dev2, devIndex) 1939 1940 t.Log("Doing first rekey") 1941 1942 // The new device should be unable to rekey on its own, and will 1943 // just set the rekey bit. 1944 kbfsOps2Dev2 := config2Dev2.KBFSOps() 1945 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 1946 kbfsOps2Dev2, rootNode1.GetFolderBranch().Tlf) 1947 if err != nil { 1948 t.Fatalf("First rekey failed %+v", err) 1949 } 1950 1951 t.Log("Doing second rekey") 1952 1953 // Do it again, to simulate the mdserver sending back this node's 1954 // own rekey request. 1955 keyManagerTestSimulateSelfRekeyBit( 1956 ctx, t, config2Dev2, rootNode1.GetFolderBranch().Tlf) 1957 1958 t.Log("Switching crypto") 1959 1960 c := make(chan struct{}, 1) 1961 // Use our other device as a standin for the paper key. 1962 clta := &cryptoLocalTrapAny{config2Dev2.Crypto(), sync.Once{}, c, config2.Crypto()} 1963 config2Dev2.SetCrypto(clta) 1964 1965 ops := getOps(config2Dev2, rootNode1.GetFolderBranch().Tlf) 1966 ops.rekeyFSM.Event(newRekeyKickoffEvent()) 1967 select { 1968 case <-c: 1969 case <-ctx.Done(): 1970 t.Fatal(ctx.Err()) 1971 } 1972 1973 // Take the mdWriterLock to ensure that the rekeyWithPrompt finishes. 1974 lState := makeFBOLockState() 1975 ops.mdWriterLock.Lock(lState) 1976 ops.mdWriterLock.Unlock(lState) 1977 1978 config2Dev2.SetCrypto(clta.Crypto) 1979 1980 rootNode2Dev2 := GetRootNodeOrBust(ctx, t, config2Dev2, name, tlf.Private) 1981 1982 kbfsOps2 := config2Dev2.KBFSOps() 1983 children, err := kbfsOps2.GetDirChildren(ctx, rootNode2Dev2) 1984 require.NoError(t, err) 1985 if _, ok := children[rootNode2Dev2.ChildName("a")]; !ok { 1986 t.Fatalf("Device 2 couldn't see the dir entry after rekey") 1987 } 1988 // user 2 creates another file to make a new revision 1989 _, _, err = kbfsOps2.CreateFile( 1990 ctx, rootNode2Dev2, testPPS("b"), false, NoExcl) 1991 if err != nil { 1992 t.Fatalf("Couldn't create file: %+v", err) 1993 } 1994 err = kbfsOps2.SyncAll(ctx, rootNode2Dev2.GetFolderBranch()) 1995 if err != nil { 1996 t.Fatalf("Couldn't sync file: %+v", err) 1997 } 1998 1999 // device 1 should be able to read the new file 2000 err = kbfsOps1.SyncFromServer(ctx, 2001 rootNode1.GetFolderBranch(), nil) 2002 if err != nil { 2003 t.Fatalf("Couldn't sync from server: %+v", err) 2004 } 2005 children, err = kbfsOps1.GetDirChildren(ctx, rootNode1) 2006 require.NoError(t, err) 2007 if _, ok := children[rootNode1.ChildName("b")]; !ok { 2008 t.Fatalf("Device 2 couldn't see the dir entry after rekey") 2009 } 2010 } 2011 2012 func testKeyManagerRekeyAddDeviceWithPromptAfterRestart(t *testing.T, ver kbfsmd.MetadataVer) { 2013 var u1, u2 kbname.NormalizedUsername = "u1", "u2" 2014 config1, uid1, ctx, cancel := kbfsOpsConcurInit(t, u1, u2) 2015 defer kbfsConcurTestShutdown(ctx, t, config1, cancel) 2016 clock := clocktest.NewTestClockNow() 2017 config1.SetClock(clock) 2018 2019 config1.SetMetadataVersion(ver) 2020 2021 config2 := ConfigAsUser(config1, u2) 2022 defer CheckConfigAndShutdown(ctx, t, config2) 2023 session2, err := config2.KBPKI().GetCurrentSession(ctx) 2024 if err != nil { 2025 t.Fatal(err) 2026 } 2027 uid2 := session2.UID 2028 2029 // Create a shared folder 2030 name := u1.String() + "," + u2.String() 2031 2032 rootNode1 := GetRootNodeOrBust(ctx, t, config1, name, tlf.Private) 2033 2034 kbfsOps1 := config1.KBFSOps() 2035 2036 // user 1 creates a file 2037 _, _, err = kbfsOps1.CreateFile(ctx, rootNode1, testPPS("a"), false, NoExcl) 2038 if err != nil { 2039 t.Fatalf("Couldn't create file: %+v", err) 2040 } 2041 err = kbfsOps1.SyncAll(ctx, rootNode1.GetFolderBranch()) 2042 if err != nil { 2043 t.Fatalf("Couldn't sync file: %+v", err) 2044 } 2045 2046 config2Dev2 := ConfigAsUser(config1, u2) 2047 defer CheckConfigAndShutdown(ctx, t, config2Dev2) 2048 2049 config2Dev2.SetKeyCache(&dummyNoKeyCache{}) 2050 2051 // Now give u2 a new device. The configs don't share a Keybase 2052 // Daemon so we have to do it in all places. 2053 AddDeviceForLocalUserOrBust(t, config1, uid2) 2054 AddDeviceForLocalUserOrBust(t, config2, uid2) 2055 devIndex := AddDeviceForLocalUserOrBust(t, config2Dev2, uid2) 2056 SwitchDeviceForLocalUserOrBust(t, config2Dev2, devIndex) 2057 // Revoke some previous device 2058 clock.Add(1 * time.Minute) 2059 RevokeDeviceForLocalUserOrBust(t, config2Dev2, uid1, 0) 2060 2061 SetGlobalMerkleRootForTestOrBust( 2062 t, config2Dev2, keybase1.MerkleRootV2{}, clock.Now()) 2063 SetKbfsMerkleRootForTestOrBust( 2064 t, config2Dev2, keybase1.MerkleTreeID_KBFS_PRIVATE, &kbfsmd.MerkleRoot{ 2065 Timestamp: clock.Now().Unix(), 2066 }) 2067 2068 t.Log("Doing first rekey") 2069 2070 // The new device should be unable to rekey on its own, and will 2071 // just set the rekey bit. 2072 kbfsOps2Dev2 := config2Dev2.KBFSOps() 2073 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 2074 kbfsOps2Dev2, rootNode1.GetFolderBranch().Tlf) 2075 if err != nil { 2076 t.Fatalf("First rekey failed %+v", err) 2077 } 2078 2079 t.Log("Doing second rekey") 2080 2081 // Do it again, to simulate the mdserver sending back this node's 2082 // own rekey request. 2083 keyManagerTestSimulateSelfRekeyBit( 2084 ctx, t, config2Dev2, rootNode1.GetFolderBranch().Tlf) 2085 2086 // Simulate a restart after the rekey bit was set 2087 ops := getOps(config2Dev2, rootNode1.GetFolderBranch().Tlf) 2088 ops.rekeyFSM.Event(newRekeyCancelEventForTest()) 2089 2090 t.Log("Doing third rekey") 2091 2092 // Try again, which should reset the timer (and so the Reset below 2093 // will be on a non-nil timer). 2094 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 2095 kbfsOps2Dev2, rootNode1.GetFolderBranch().Tlf) 2096 if err != nil { 2097 t.Fatalf("Third rekey failed %+v", err) 2098 } 2099 2100 t.Log("Switching crypto") 2101 2102 c := make(chan struct{}, 1) 2103 // Use our other device as a standin for the paper key. 2104 clta := &cryptoLocalTrapAny{config2Dev2.Crypto(), sync.Once{}, c, config2.Crypto()} 2105 config2Dev2.SetCrypto(clta) 2106 2107 ops.rekeyFSM.Event(newRekeyKickoffEvent()) 2108 select { 2109 case <-c: 2110 case <-ctx.Done(): 2111 t.Fatal(ctx.Err()) 2112 } 2113 2114 // Take the mdWriterLock to ensure that the rekeyWithPrompt finishes. 2115 lState := makeFBOLockState() 2116 ops.mdWriterLock.Lock(lState) 2117 ops.mdWriterLock.Unlock(lState) 2118 2119 config2Dev2.SetCrypto(clta.Crypto) 2120 2121 rootNode2Dev2 := GetRootNodeOrBust(ctx, t, config2Dev2, name, tlf.Private) 2122 2123 kbfsOps2 := config2Dev2.KBFSOps() 2124 children, err := kbfsOps2.GetDirChildren(ctx, rootNode2Dev2) 2125 require.NoError(t, err) 2126 if _, ok := children[rootNode2Dev2.ChildName("a")]; !ok { 2127 t.Fatalf("Device 2 couldn't see the dir entry after rekey") 2128 } 2129 // user 2 creates another file to make a new revision 2130 _, _, err = kbfsOps2.CreateFile( 2131 ctx, rootNode2Dev2, testPPS("b"), false, NoExcl) 2132 if err != nil { 2133 t.Fatalf("Couldn't create file: %+v", err) 2134 } 2135 err = kbfsOps2.SyncAll(ctx, rootNode2Dev2.GetFolderBranch()) 2136 if err != nil { 2137 t.Fatalf("Couldn't sync file: %+v", err) 2138 } 2139 } 2140 2141 func testKeyManagerRekeyAddDeviceWithPromptViaFolderAccess(t *testing.T, ver kbfsmd.MetadataVer) { 2142 var u1, u2 kbname.NormalizedUsername = "u1", "u2" 2143 config1, _, ctx, cancel := kbfsOpsConcurInit(t, u1, u2) 2144 defer kbfsConcurTestShutdown(ctx, t, config1, cancel) 2145 2146 config1.SetMetadataVersion(ver) 2147 2148 config2 := ConfigAsUser(config1, u2) 2149 defer CheckConfigAndShutdown(ctx, t, config2) 2150 session2, err := config2.KBPKI().GetCurrentSession(ctx) 2151 if err != nil { 2152 t.Fatal(err) 2153 } 2154 uid2 := session2.UID 2155 2156 // Create a shared folder 2157 name := u1.String() + "," + u2.String() 2158 2159 rootNode1 := GetRootNodeOrBust(ctx, t, config1, name, tlf.Private) 2160 config2Dev2 := ConfigAsUser(config1, u2) 2161 defer CheckConfigAndShutdown(ctx, t, config2Dev2) 2162 2163 config2Dev2.SetKeyCache(&dummyNoKeyCache{}) 2164 2165 // Now give u2 a new device. The configs don't share a Keybase 2166 // Daemon so we have to do it in all places. 2167 AddDeviceForLocalUserOrBust(t, config1, uid2) 2168 AddDeviceForLocalUserOrBust(t, config2, uid2) 2169 devIndex := AddDeviceForLocalUserOrBust(t, config2Dev2, uid2) 2170 SwitchDeviceForLocalUserOrBust(t, config2Dev2, devIndex) 2171 2172 t.Log("Doing first rekey") 2173 2174 // The new device should be unable to rekey on its own, and will 2175 // just set the rekey bit. 2176 kbfsOps2Dev2 := config2Dev2.KBFSOps() 2177 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 2178 kbfsOps2Dev2, rootNode1.GetFolderBranch().Tlf) 2179 if err != nil { 2180 t.Fatalf("First rekey failed %+v", err) 2181 } 2182 2183 ops := getOps(config2Dev2, rootNode1.GetFolderBranch().Tlf) 2184 2185 // Make sure just the rekey bit is set 2186 if !ops.head.IsRekeySet() { 2187 t.Fatalf("Couldn't set rekey bit") 2188 } 2189 2190 t.Log("Switching crypto") 2191 2192 // Allow the prompt rekey attempt to fail by using dev2's crypto 2193 // (which still isn't keyed for) 2194 c := make(chan struct{}, 1) 2195 clta := &cryptoLocalTrapAny{config2Dev2.Crypto(), sync.Once{}, c, config2Dev2.Crypto()} 2196 config2Dev2.SetCrypto(clta) 2197 ops.rekeyFSM.Event(newRekeyKickoffEvent()) 2198 select { 2199 case <-c: 2200 case <-ctx.Done(): 2201 t.Fatal(ctx.Err()) 2202 } 2203 // Make sure the rekey attempt is finished by taking the lock. 2204 // Keep the lock for a while, to control when the second rekey starts. 2205 lState := makeFBOLockState() 2206 func() { 2207 ops.mdWriterLock.Lock(lState) 2208 defer ops.mdWriterLock.Unlock(lState) 2209 2210 // Now cause a paper prompt unlock via a folder access 2211 errCh := make(chan error, 1) 2212 go func() { 2213 _, err := GetRootNodeForTest(ctx, config2Dev2, name, tlf.Private) 2214 select { 2215 case errCh <- err: 2216 case <-ctx.Done(): 2217 errCh <- errors.WithStack(ctx.Err()) 2218 } 2219 }() 2220 select { 2221 case err = <-errCh: 2222 case <-ctx.Done(): 2223 t.Fatal(ctx.Err()) 2224 } 2225 if _, ok := err.(NeedSelfRekeyError); !ok { 2226 t.Fatalf("Got unexpected error when reading with new key: %+v", err) 2227 } 2228 2229 t.Log("Switching crypto again") 2230 2231 // Let the background rekeyer decrypt. 2232 c = make(chan struct{}, 1) 2233 clta = &cryptoLocalTrapAny{config2Dev2.Crypto(), sync.Once{}, c, config2.Crypto()} 2234 config2Dev2.SetCrypto(clta) 2235 }() 2236 2237 t.Log("Waiting for rekey attempt") 2238 2239 select { 2240 case <-c: 2241 case <-ctx.Done(): 2242 t.Fatal(ctx.Err()) 2243 } 2244 // Make sure the rekey attempt is finished 2245 ops.mdWriterLock.Lock(lState) 2246 ops.mdWriterLock.Unlock(lState) 2247 2248 t.Log("Getting the root node, which should now succeed") 2249 2250 GetRootNodeOrBust(ctx, t, config2Dev2, name, tlf.Private) 2251 } 2252 2253 func testKeyManagerRekeyMinimal(t *testing.T, ver kbfsmd.MetadataVer) { 2254 var u1, u2 kbname.NormalizedUsername = "u1", "u2" 2255 config1, _, ctx, cancel := kbfsOpsConcurInit(t, u1, u2) 2256 defer kbfsConcurTestShutdown(ctx, t, config1, cancel) 2257 clock := clocktest.NewTestClockNow() 2258 config1.SetClock(clock) 2259 2260 config1.SetMetadataVersion(ver) 2261 2262 // User 2 is in minimal mode. 2263 config2 := ConfigAsUserWithMode(config1, u2, InitMinimal) 2264 defer CheckConfigAndShutdown(ctx, t, config2) 2265 session2, err := config2.KBPKI().GetCurrentSession(ctx) 2266 if err != nil { 2267 t.Fatal(err) 2268 } 2269 uid2 := session2.UID 2270 2271 // Create a shared folder 2272 name := u1.String() + "," + u2.String() 2273 2274 rootNode1 := GetRootNodeOrBust(ctx, t, config1, name, tlf.Private) 2275 2276 kbfsOps1 := config1.KBFSOps() 2277 2278 // user 1 creates a file 2279 _, _, err = kbfsOps1.CreateFile(ctx, rootNode1, testPPS("a"), false, NoExcl) 2280 if err != nil { 2281 t.Fatalf("Couldn't create file: %+v", err) 2282 } 2283 err = kbfsOps1.SyncAll(ctx, rootNode1.GetFolderBranch()) 2284 if err != nil { 2285 t.Fatalf("Couldn't sync file: %+v", err) 2286 } 2287 2288 // Device 2 is in default mode, so we can check that the rekey 2289 // worked. 2290 config2Dev2 := ConfigAsUser(config1, u2) 2291 defer CheckConfigAndShutdown(ctx, t, config2Dev2) 2292 2293 // Now give u2 a new device. The configs don't share a Keybase 2294 // Daemon so we have to do it in all places. 2295 AddDeviceForLocalUserOrBust(t, config1, uid2) 2296 AddDeviceForLocalUserOrBust(t, config2, uid2) 2297 devIndex := AddDeviceForLocalUserOrBust(t, config2Dev2, uid2) 2298 SwitchDeviceForLocalUserOrBust(t, config2Dev2, devIndex) 2299 2300 // user 2 should be unable to read the data now since its device 2301 // wasn't registered when the folder was originally created. 2302 _, err = GetRootNodeForTest(ctx, config2Dev2, name, tlf.Private) 2303 if _, ok := err.(NeedSelfRekeyError); !ok { 2304 t.Fatalf("Got unexpected error when reading with new key: %+v", err) 2305 } 2306 2307 // Have the minimal instance do the rekey. 2308 _, err = RequestRekeyAndWaitForOneFinishEvent(ctx, 2309 config2.KBFSOps(), rootNode1.GetFolderBranch().Tlf) 2310 if err != nil { 2311 t.Fatalf("Couldn't rekey: %+v", err) 2312 } 2313 2314 root2Dev2 := GetRootNodeOrBust(ctx, t, config2Dev2, name, tlf.Private) 2315 kbfsOps2Dev2 := config2Dev2.KBFSOps() 2316 err = kbfsOps2Dev2.SyncFromServer(ctx, 2317 root2Dev2.GetFolderBranch(), nil) 2318 if err != nil { 2319 t.Fatalf("Couldn't sync from server: %+v", err) 2320 } 2321 2322 children, err := kbfsOps2Dev2.GetDirChildren(ctx, root2Dev2) 2323 require.NoError(t, err) 2324 if _, ok := children[root2Dev2.ChildName("a")]; !ok { 2325 t.Fatalf("Device 2 couldn't see the dir entry") 2326 } 2327 } 2328 2329 // maybeReplaceContext, defined on *protectedContext, enables replacing context 2330 // stored in protectedContext. 2331 // 2332 // This is importantly defined in a _test.go file since we should not use it 2333 // anywhere other than in tests. 2334 // 2335 // For now, the only application for this is to cause states in rekey_fsm 2336 // to replace existing context when new request comes in. This is needed 2337 // because stallers store staller key in context, and context needs to be 2338 // updated in states in order for stalling to be effective. 2339 func (c *protectedContext) maybeReplaceContext(newCtx context.Context) { 2340 c.mu.Lock() 2341 defer c.mu.Unlock() 2342 if c.log != nil { 2343 c.log.CDebugf(c.ctx, "Replacing context") 2344 defer c.log.CDebugf(newCtx, "Context replaced") 2345 } 2346 c.ctx = newCtx 2347 } 2348 2349 func TestKeyManagerGetTeamTLFCryptKey(t *testing.T) { 2350 var u1, u2 kbname.NormalizedUsername = "u1", "u2" 2351 config1, uid1, ctx, cancel := kbfsOpsConcurInit(t, u1, u2) 2352 defer kbfsConcurTestShutdown(ctx, t, config1, cancel) 2353 2354 config2 := ConfigAsUser(config1, u2) 2355 defer CheckConfigAndShutdown(ctx, t, config2) 2356 session2, err := config2.KBPKI().GetCurrentSession(ctx) 2357 if err != nil { 2358 t.Fatal(err) 2359 } 2360 uid2 := session2.UID 2361 2362 // These are deterministic, and should add the same TeamInfos for 2363 // both user configs. 2364 name := kbname.NormalizedUsername("t1") 2365 teamInfos := AddEmptyTeamsForTestOrBust(t, config1, name) 2366 _ = AddEmptyTeamsForTestOrBust(t, config2, name) 2367 tid := teamInfos[0].TID 2368 AddTeamWriterForTestOrBust(t, config1, tid, uid1) 2369 AddTeamWriterForTestOrBust(t, config2, tid, uid1) 2370 AddTeamWriterForTestOrBust(t, config1, tid, uid2) 2371 AddTeamWriterForTestOrBust(t, config2, tid, uid2) 2372 2373 tlfID := tlf.FakeID(1, tlf.SingleTeam) 2374 h := tlfhandle.NewHandle( 2375 tlf.SingleTeam, 2376 map[keybase1.UserOrTeamID]kbname.NormalizedUsername{ 2377 tid.AsUserOrTeam(): name, 2378 }, nil, nil, tlf.CanonicalName(name), tlf.NullID) 2379 2380 rmd, err := makeInitialRootMetadata(kbfsmd.SegregatedKeyBundlesVer, tlfID, h) 2381 require.NoError(t, err) 2382 rmd.bareMd.SetLatestKeyGenerationForTeamTLF(teamInfos[0].LatestKeyGen) 2383 // Make sure the MD looks readable. 2384 rmd.data.Dir.BlockPointer = data.BlockPointer{ID: kbfsblock.FakeID(1)} 2385 2386 // Both users should see the same key. 2387 key1, err := config1.KeyManager().GetTLFCryptKeyForEncryption(ctx, rmd) 2388 require.NoError(t, err) 2389 key2, err := config2.KeyManager().GetTLFCryptKeyForEncryption(ctx, rmd) 2390 require.NoError(t, err) 2391 require.Equal(t, key1, key2) 2392 2393 // Bump the key generation. 2394 AddTeamKeyForTestOrBust(t, config1, tid) 2395 AddTeamKeyForTestOrBust(t, config2, tid) 2396 rmd2, err := rmd.MakeSuccessor(context.Background(), 2397 config1.MetadataVersion(), config1.Codec(), 2398 config1.KeyManager(), config1.KBPKI(), config1.KBPKI(), 2399 config1, kbfsmd.FakeID(2), true) 2400 require.NoError(t, err) 2401 2402 // Both users should see the same new key. 2403 key1b, err := config1.KeyManager().GetTLFCryptKeyForEncryption(ctx, rmd2) 2404 require.NoError(t, err) 2405 key2b, err := config2.KeyManager().GetTLFCryptKeyForEncryption(ctx, rmd2) 2406 require.NoError(t, err) 2407 require.Equal(t, key1b, key2b) 2408 require.NotEqual(t, key1, key1b) 2409 } 2410 2411 func testKeyManagerGetImplicitTeamTLFCryptKey(t *testing.T, ty tlf.Type) { 2412 var u1, u2 kbname.NormalizedUsername = "u1", "u2" 2413 config1, _, ctx, cancel := kbfsOpsConcurInit(t, u1, u2) 2414 defer kbfsConcurTestShutdown(ctx, t, config1, cancel) 2415 2416 config2 := ConfigAsUser(config1, u2) 2417 defer CheckConfigAndShutdown(ctx, t, config2) 2418 2419 // These are deterministic, and should add the same 2420 // ImplicitTeamInfos for both user configs. 2421 iname := "u1,u2" 2422 err := EnableImplicitTeamsForTest(config1) 2423 require.NoError(t, err) 2424 teamID := AddImplicitTeamForTestOrBust(t, config1, iname, "", 1, ty) 2425 _ = AddImplicitTeamForTestOrBust(t, config2, iname, "", 1, ty) 2426 tlfID := tlf.FakeID(1, ty) 2427 2428 asUserName := kbname.NormalizedUsername(iname) 2429 h := tlfhandle.NewHandle( 2430 ty, map[keybase1.UserOrTeamID]kbname.NormalizedUsername{ 2431 teamID.AsUserOrTeam(): asUserName, 2432 }, nil, nil, tlf.CanonicalName(asUserName), tlfID) 2433 2434 _, latestKeyGen, err := config1.KBPKI().GetTeamTLFCryptKeys( 2435 ctx, teamID, kbfsmd.UnspecifiedKeyGen, 2436 keybase1.OfflineAvailability_NONE) 2437 require.NoError(t, err) 2438 2439 rmd, err := makeInitialRootMetadata(config1.MetadataVersion(), tlfID, h) 2440 require.NoError(t, err) 2441 rmd.bareMd.SetLatestKeyGenerationForTeamTLF(latestKeyGen) 2442 // Make sure the MD looks readable. 2443 rmd.data.Dir.BlockPointer = data.BlockPointer{ID: kbfsblock.FakeID(1)} 2444 2445 // Both users should see the same key. 2446 key1, err := config1.KeyManager().GetTLFCryptKeyForEncryption(ctx, rmd) 2447 require.NoError(t, err) 2448 key2, err := config2.KeyManager().GetTLFCryptKeyForEncryption(ctx, rmd) 2449 require.NoError(t, err) 2450 require.Equal(t, key1, key2) 2451 2452 // Bump the key generation. 2453 AddTeamKeyForTestOrBust(t, config1, teamID) 2454 AddTeamKeyForTestOrBust(t, config2, teamID) 2455 rmd2, err := rmd.MakeSuccessor(context.Background(), 2456 config1.MetadataVersion(), config1.Codec(), 2457 config1.KeyManager(), config1.KBPKI(), config1.KBPKI(), 2458 config1, kbfsmd.FakeID(2), true) 2459 require.NoError(t, err) 2460 2461 // Both users should see the same new key. 2462 key1b, err := config1.KeyManager().GetTLFCryptKeyForEncryption(ctx, rmd2) 2463 require.NoError(t, err) 2464 key2b, err := config2.KeyManager().GetTLFCryptKeyForEncryption(ctx, rmd2) 2465 require.NoError(t, err) 2466 require.Equal(t, key1b, key2b) 2467 if ty == tlf.Public { 2468 // Bumping the key generation shouldn't do anything for public TLFs. 2469 require.Equal(t, key1, key1b) 2470 } else { 2471 require.NotEqual(t, key1, key1b) 2472 } 2473 } 2474 2475 func TestKeyManagerGetPrivateImplicitTeamTLFCryptKey(t *testing.T) { 2476 testKeyManagerGetImplicitTeamTLFCryptKey(t, tlf.Private) 2477 } 2478 2479 func TestKeyManagerGetPublicImplicitTeamTLFCryptKey(t *testing.T) { 2480 testKeyManagerGetImplicitTeamTLFCryptKey(t, tlf.Public) 2481 } 2482 2483 func TestKeyManager(t *testing.T) { 2484 tests := []func(*testing.T, kbfsmd.MetadataVer){ 2485 testKeyManagerPublicTLFCryptKey, 2486 testKeyManagerCachedSecretKeyForEncryptionSuccess, 2487 testKeyManagerCachedSecretKeyForMDDecryptionSuccess, 2488 testKeyManagerCachedSecretKeyForBlockDecryptionSuccess, 2489 testKeyManagerUncachedSecretKeyForEncryptionSuccess, 2490 testKeyManagerUncachedSecretKeyForMDDecryptionSuccess, 2491 testKeyManagerUncachedSecretKeyForBlockDecryptionSuccess, 2492 testKeyManagerRekeySuccessPrivate, 2493 testKeyManagerRekeyResolveAgainSuccessPublic, 2494 testKeyManagerRekeyResolveAgainSuccessPublicSelf, 2495 testKeyManagerRekeyResolveAgainSuccessPrivate, 2496 testKeyManagerPromoteReaderSuccess, 2497 testKeyManagerPromoteReaderSelf, 2498 testKeyManagerReaderRekeyShouldNotPromote, 2499 testKeyManagerReaderRekeyResolveAgainSuccessPrivate, 2500 testKeyManagerRekeyResolveAgainNoChangeSuccessPrivate, 2501 testKeyManagerRekeyAddAndRevokeDevice, 2502 testKeyManagerRekeyAddWriterAndReaderDevice, 2503 testKeyManagerSelfRekeyAcrossDevices, 2504 testKeyManagerReaderRekey, 2505 testKeyManagerReaderRekeyAndRevoke, 2506 testKeyManagerRekeyBit, 2507 testKeyManagerRekeyAddAndRevokeDeviceWithConflict, 2508 testKeyManagerRekeyAddDeviceWithPrompt, 2509 testKeyManagerRekeyAddDeviceWithPromptAfterRestart, 2510 testKeyManagerRekeyAddDeviceWithPromptViaFolderAccess, 2511 testKeyManagerRekeyMinimal, 2512 } 2513 runTestsOverMetadataVers(t, "testKeyManager", tests) 2514 }