github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/libkbfs/md_ops_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 "crypto/rand" 9 "errors" 10 "fmt" 11 "sync" 12 "testing" 13 "time" 14 15 "github.com/golang/mock/gomock" 16 "github.com/keybase/client/go/kbfs/idutil" 17 "github.com/keybase/client/go/kbfs/kbfscodec" 18 "github.com/keybase/client/go/kbfs/kbfscrypto" 19 "github.com/keybase/client/go/kbfs/kbfsmd" 20 "github.com/keybase/client/go/kbfs/libkey" 21 "github.com/keybase/client/go/kbfs/test/clocktest" 22 "github.com/keybase/client/go/kbfs/tlf" 23 "github.com/keybase/client/go/kbfs/tlfhandle" 24 kbname "github.com/keybase/client/go/kbun" 25 "github.com/keybase/client/go/protocol/keybase1" 26 merkle "github.com/keybase/go-merkle-tree" 27 "github.com/stretchr/testify/require" 28 "golang.org/x/net/context" 29 ) 30 31 type shimCrypto struct { 32 Crypto 33 pure cryptoPure 34 key kbfscrypto.SigningKey 35 } 36 37 func (c shimCrypto) Sign( 38 ctx context.Context, data []byte) (kbfscrypto.SignatureInfo, error) { 39 return c.key.Sign(data), nil 40 } 41 42 func (c shimCrypto) SignForKBFS( 43 ctx context.Context, data []byte) (kbfscrypto.SignatureInfo, error) { 44 return c.key.SignForKBFS(data) 45 } 46 47 func (c shimCrypto) Verify( 48 msg []byte, sigInfo kbfscrypto.SignatureInfo) (err error) { 49 return kbfscrypto.Verify(msg, sigInfo) 50 } 51 52 func injectShimCrypto(config Config) { 53 signingKey := kbfscrypto.MakeFakeSigningKeyOrBust("test key") 54 crypto := shimCrypto{ 55 config.Crypto(), 56 MakeCryptoCommon(kbfscodec.NewMsgpack(), makeBlockCryptV1()), 57 signingKey, 58 } 59 config.SetCrypto(crypto) 60 } 61 62 func mdOpsInit(t *testing.T, ver kbfsmd.MetadataVer) (mockCtrl *gomock.Controller, 63 config *ConfigMock, ctx context.Context) { 64 ctr := NewSafeTestReporter(t) 65 mockCtrl = gomock.NewController(ctr) 66 config = NewConfigMock(mockCtrl, ctr) 67 config.SetMetadataVersion(ver) 68 mdops := NewMDOpsStandard(config) 69 config.SetMDOps(mdops) 70 config.SetCodec(kbfscodec.NewMsgpack()) 71 config.SetKeyBundleCache(kbfsmd.NewKeyBundleCacheLRU(0)) 72 config.mockMdserv.EXPECT().OffsetFromServerTime(). 73 Return(time.Duration(0), true).AnyTimes() 74 config.mockClock.EXPECT().Now().Return(time.Now()).AnyTimes() 75 injectShimCrypto(config) 76 interposeDaemonKBPKI(config, "alice", "bob", "charlie") 77 ctx = context.Background() 78 79 // Don't test implicit teams. 80 config.mockKbpki.EXPECT().ResolveImplicitTeam( 81 gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 82 AnyTimes().Return(idutil.ImplicitTeamInfo{}, errors.New("No such team")) 83 // Don't cache IDs. 84 config.mockMdcache.EXPECT().GetIDForHandle(gomock.Any()).AnyTimes(). 85 Return(tlf.NullID, NoSuchTlfIDError{nil}) 86 config.mockMdcache.EXPECT().PutIDForHandle(gomock.Any(), gomock.Any()). 87 AnyTimes().Return(nil) 88 mockNormalizeSocialAssertion(config) 89 90 return mockCtrl, config, ctx 91 } 92 93 func mdOpsShutdown(mockCtrl *gomock.Controller, config *ConfigMock) { 94 config.ctr.CheckForFailures() 95 mockCtrl.Finish() 96 } 97 98 func addPrivateDataToRMD(t *testing.T, 99 codec kbfscodec.Codec, rmd *RootMetadata, h *tlfhandle.Handle, 100 pmd PrivateMetadata) { 101 rmd.SetRevision(kbfsmd.Revision(1)) 102 // TODO: Will have to change this for private folders if we 103 // un-mock out those tests. 104 buf, err := codec.Encode(pmd) 105 require.NoError(t, err) 106 rmd.SetSerializedPrivateMetadata(buf) 107 rmd.SetLastModifyingWriter(h.FirstResolvedWriter().AsUserOrBust()) 108 rmd.SetLastModifyingUser(h.FirstResolvedWriter().AsUserOrBust()) 109 if h.Type() == tlf.Private { 110 rmd.fakeInitialRekey() 111 } 112 } 113 114 func addFakeRMDData(t *testing.T, 115 codec kbfscodec.Codec, rmd *RootMetadata, h *tlfhandle.Handle) { 116 addPrivateDataToRMD(t, codec, rmd, h, PrivateMetadata{}) 117 } 118 119 func newRMDS(t *testing.T, config Config, h *tlfhandle.Handle) ( 120 *RootMetadataSigned, kbfsmd.ExtraMetadata) { 121 id := h.TlfID() 122 if id == tlf.NullID { 123 id = tlf.FakeID(1, h.Type()) 124 } 125 126 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 127 require.NoError(t, err) 128 129 addFakeRMDData(t, config.Codec(), rmd, h) 130 ctx := context.Background() 131 132 // Encode and sign writer metadata. 133 err = rmd.bareMd.SignWriterMetadataInternally(ctx, config.Codec(), config.Crypto()) 134 require.NoError(t, err) 135 136 rmds, err := SignBareRootMetadata( 137 ctx, config.Codec(), config.Crypto(), config.Crypto(), 138 rmd.bareMd, time.Now()) 139 require.NoError(t, err) 140 return rmds, rmd.extra 141 } 142 143 func verifyMDForPublic(config *ConfigMock, rmds *RootMetadataSigned, 144 hasVerifyingKeyErr error) { 145 config.mockKbpki.EXPECT().HasVerifyingKey( 146 gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 147 AnyTimes().Return(hasVerifyingKeyErr) 148 if hasVerifyingKeyErr == nil { 149 config.mockMdcache.EXPECT().Put(gomock.Any()) 150 } 151 } 152 153 // kmdMatcher implements the gomock.Matcher interface to compare 154 // KeyMetadata objects. 155 type kmdMatcher struct { 156 kmd libkey.KeyMetadata 157 } 158 159 func (m kmdMatcher) Matches(x interface{}) bool { 160 kmd, ok := x.(libkey.KeyMetadata) 161 if !ok { 162 return false 163 } 164 return (m.kmd.TlfID() == kmd.TlfID()) && 165 (m.kmd.LatestKeyGeneration() == kmd.LatestKeyGeneration()) 166 } 167 168 func (m kmdMatcher) String() string { 169 return fmt.Sprintf("Matches KeyMetadata with TlfID=%s and key generation %d", 170 m.kmd.TlfID(), m.kmd.LatestKeyGeneration()) 171 } 172 173 func expectGetTLFCryptKeyForEncryption(config *ConfigMock, kmd libkey.KeyMetadata) { 174 config.mockKeyman.EXPECT().GetTLFCryptKeyForEncryption(gomock.Any(), 175 kmdMatcher{kmd}).Return(kbfscrypto.TLFCryptKey{}, nil) 176 } 177 178 func expectGetTLFCryptKeyForMDDecryptionAtMostOnce(config *ConfigMock, 179 kmd libkey.KeyMetadata) { 180 config.mockKeyman.EXPECT().GetTLFCryptKeyForMDDecryption(gomock.Any(), 181 kmdMatcher{kmd}, kmdMatcher{kmd}).MaxTimes(1).Return( 182 kbfscrypto.TLFCryptKey{}, nil) 183 } 184 185 func verifyMDForPrivateHelper( 186 config *ConfigMock, rmds *RootMetadataSigned, minTimes, maxTimes int, 187 forceFinal bool) { 188 mdCopy, err := rmds.MD.DeepCopy(config.Codec()) 189 if err != nil { 190 panic(err) 191 } 192 fakeRMD := RootMetadata{ 193 bareMd: mdCopy, 194 } 195 expectGetTLFCryptKeyForMDDecryptionAtMostOnce(config, &fakeRMD) 196 var pmd PrivateMetadata 197 config.mockCrypto.EXPECT().DecryptPrivateMetadata( 198 gomock.Any(), kbfscrypto.TLFCryptKey{}). 199 MinTimes(minTimes).MaxTimes(maxTimes).Return(pmd, nil) 200 201 config.mockKbpki.EXPECT().HasVerifyingKey( 202 gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). 203 AnyTimes().Return(nil) 204 config.mockMdcache.EXPECT().Put(gomock.Any()).AnyTimes() 205 config.mockKeyman.EXPECT().GetFirstTLFCryptKey(gomock.Any(), gomock.Any()). 206 AnyTimes().Return(kbfscrypto.TLFCryptKey{}, nil) 207 } 208 209 func verifyMDForPrivate( 210 config *ConfigMock, rmds *RootMetadataSigned) { 211 verifyMDForPrivateHelper(config, rmds, 1, 1, false) 212 } 213 214 func putMDForPrivate(config *ConfigMock, rmd *RootMetadata) { 215 expectGetTLFCryptKeyForEncryption(config, rmd) 216 config.mockCrypto.EXPECT().EncryptPrivateMetadata( 217 rmd.data, kbfscrypto.TLFCryptKey{}).Return( 218 kbfscrypto.EncryptedPrivateMetadata{}, nil) 219 config.mockBsplit.EXPECT().ShouldEmbedData(gomock.Any()).Return(true) 220 config.mockMdserv.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any(), 221 nil, gomock.Any()).Return(nil) 222 config.mockMdcache.EXPECT().Replace(gomock.Any(), gomock.Any()) 223 } 224 225 func testMDOpsGetIDForHandlePublicSuccess( 226 t *testing.T, ver kbfsmd.MetadataVer) { 227 mockCtrl, config, ctx := mdOpsInit(t, ver) 228 defer mdOpsShutdown(mockCtrl, config) 229 230 id := tlf.FakeID(1, tlf.Public) 231 h := parseTlfHandleOrBust(t, config, "alice,bob", tlf.Public, id) 232 rmds, _ := newRMDS(t, config, h) 233 h.SetTlfID(tlf.NullID) 234 235 verifyMDForPublic(config, rmds, nil) 236 237 config.mockMdserv.EXPECT().GetForHandle(ctx, h.ToBareHandleOrBust(), 238 kbfsmd.Merged, nil).Return(id, rmds, nil) 239 240 id2, err := config.MDOps().GetIDForHandle(ctx, h) 241 require.NoError(t, err) 242 require.Equal(t, id, id2) 243 } 244 245 func expectGetKeyBundles(ctx context.Context, config *ConfigMock, extra kbfsmd.ExtraMetadata) { 246 if extraV3, ok := extra.(*kbfsmd.ExtraMetadataV3); ok { 247 wkb := extraV3.GetWriterKeyBundle() 248 rkb := extraV3.GetReaderKeyBundle() 249 config.mockMdserv.EXPECT().GetKeyBundles( 250 ctx, gomock.Any(), gomock.Any(), gomock.Any()). 251 Return(&wkb, &rkb, nil) 252 } 253 } 254 255 func testMDOpsGetIDForHandlePrivateSuccess( 256 t *testing.T, ver kbfsmd.MetadataVer) { 257 mockCtrl, config, ctx := mdOpsInit(t, ver) 258 defer mdOpsShutdown(mockCtrl, config) 259 260 id := tlf.FakeID(1, tlf.Private) 261 h := parseTlfHandleOrBust(t, config, "alice,bob", tlf.Private, id) 262 rmds, extra := newRMDS(t, config, h) 263 h.SetTlfID(tlf.NullID) 264 265 verifyMDForPrivate(config, rmds) 266 267 config.mockMdserv.EXPECT().GetForHandle(ctx, h.ToBareHandleOrBust(), 268 kbfsmd.Merged, nil).Return(id, rmds, nil) 269 expectGetKeyBundles(ctx, config, extra) 270 271 id2, err := config.MDOps().GetIDForHandle(ctx, h) 272 require.NoError(t, err) 273 require.Equal(t, id, id2) 274 } 275 276 func testMDOpsGetIDForUnresolvedHandlePublicSuccess( 277 t *testing.T, ver kbfsmd.MetadataVer) { 278 mockCtrl, config, ctx := mdOpsInit(t, ver) 279 defer mdOpsShutdown(mockCtrl, config) 280 281 id := tlf.FakeID(1, tlf.Public) 282 h := parseTlfHandleOrBust(t, config, "alice,bob", tlf.Public, id) 283 rmds, _ := newRMDS(t, config, h) 284 h.SetTlfID(tlf.NullID) 285 286 // Do this before setting tlfHandle to nil. 287 verifyMDForPublic(config, rmds, nil) 288 289 hUnresolved, err := tlfhandle.ParseHandle( 290 ctx, config.KBPKI(), tlfhandle.ConstIDGetter{ID: id}, nil, 291 "alice,bob@twitter", tlf.Public) 292 require.NoError(t, err) 293 hUnresolved.SetTlfID(tlf.NullID) 294 295 config.mockMdserv.EXPECT().GetForHandle(ctx, 296 hUnresolved.ToBareHandleOrBust(), kbfsmd.Merged, nil).Return( 297 id, rmds, nil).Times(2) 298 299 // First time should fail. 300 _, err = config.MDOps().GetIDForHandle(ctx, hUnresolved) 301 if _, ok := err.(tlfhandle.HandleMismatchError); !ok { 302 t.Errorf("Got unexpected error on bad handle check test: %v", err) 303 } 304 305 daemon := config.KeybaseService().(*KeybaseDaemonLocal) 306 daemon.AddNewAssertionForTestOrBust("bob", "bob@twitter") 307 308 // Second time should succeed. 309 if _, err := config.MDOps().GetIDForHandle(ctx, hUnresolved); err != nil { 310 t.Errorf("Got error on get: %v", err) 311 } 312 } 313 314 func testMDOpsGetIDForUnresolvedMdHandlePublicSuccess( 315 t *testing.T, ver kbfsmd.MetadataVer) { 316 mockCtrl, config, ctx := mdOpsInit(t, ver) 317 defer mdOpsShutdown(mockCtrl, config) 318 319 id := tlf.FakeID(1, tlf.Public) 320 mdHandle1, err := tlfhandle.ParseHandle( 321 ctx, config.KBPKI(), tlfhandle.ConstIDGetter{ID: id}, nil, 322 "alice,dave@twitter", tlf.Public) 323 require.NoError(t, err) 324 mdHandle1.SetTlfID(tlf.NullID) 325 326 mdHandle2, err := tlfhandle.ParseHandle( 327 ctx, config.KBPKI(), tlfhandle.ConstIDGetter{ID: id}, nil, 328 "alice,bob,charlie", tlf.Public) 329 require.NoError(t, err) 330 mdHandle2.SetTlfID(tlf.NullID) 331 332 mdHandle3, err := tlfhandle.ParseHandle( 333 ctx, config.KBPKI(), tlfhandle.ConstIDGetter{ID: id}, nil, 334 "alice,bob@twitter,charlie@twitter", tlf.Public) 335 require.NoError(t, err) 336 mdHandle3.SetTlfID(tlf.NullID) 337 338 rmds1, _ := newRMDS(t, config, mdHandle1) 339 340 rmds2, _ := newRMDS(t, config, mdHandle2) 341 342 rmds3, _ := newRMDS(t, config, mdHandle3) 343 344 // Do this before setting tlfHandles to nil. 345 verifyMDForPublic(config, rmds2, nil) 346 verifyMDForPublic(config, rmds3, nil) 347 348 h, err := tlfhandle.ParseHandle( 349 ctx, config.KBPKI(), tlfhandle.ConstIDGetter{ID: id}, nil, 350 "alice,bob,charlie@twitter", tlf.Public) 351 require.NoError(t, err) 352 h.SetTlfID(tlf.NullID) 353 354 config.mockMdserv.EXPECT().GetForHandle(ctx, h.ToBareHandleOrBust(), 355 kbfsmd.Merged, nil).Return(id, rmds1, nil) 356 357 // First time should fail. 358 _, err = config.MDOps().GetIDForHandle(ctx, h) 359 if _, ok := err.(tlfhandle.HandleMismatchError); !ok { 360 t.Errorf("Got unexpected error on bad handle check test: %v", err) 361 } 362 363 daemon := config.KeybaseService().(*KeybaseDaemonLocal) 364 daemon.AddNewAssertionForTestOrBust("bob", "bob@twitter") 365 daemon.AddNewAssertionForTestOrBust("charlie", "charlie@twitter") 366 367 config.mockMdserv.EXPECT().GetForHandle(ctx, h.ToBareHandleOrBust(), 368 kbfsmd.Merged, nil).Return(id, rmds2, nil) 369 370 // Second time should succeed. 371 if _, err := config.MDOps().GetIDForHandle(ctx, h); err != nil { 372 t.Errorf("Got error on get: %v", err) 373 } 374 375 config.mockMdserv.EXPECT().GetForHandle(ctx, h.ToBareHandleOrBust(), 376 kbfsmd.Merged, nil).Return(id, rmds3, nil) 377 378 if _, err := config.MDOps().GetIDForHandle(ctx, h); err != nil { 379 t.Errorf("Got error on get: %v", err) 380 } 381 } 382 383 func testMDOpsGetIDForUnresolvedHandlePublicFailure( 384 t *testing.T, ver kbfsmd.MetadataVer) { 385 mockCtrl, config, ctx := mdOpsInit(t, ver) 386 defer mdOpsShutdown(mockCtrl, config) 387 388 id := tlf.FakeID(1, tlf.Public) 389 h := parseTlfHandleOrBust(t, config, "alice,bob", tlf.Public, id) 390 rmds, _ := newRMDS(t, config, h) 391 392 hUnresolved, err := tlfhandle.ParseHandle( 393 ctx, config.KBPKI(), tlfhandle.ConstIDGetter{ID: id}, nil, 394 "alice,bob@github,bob@twitter", tlf.Public) 395 require.NoError(t, err) 396 hUnresolved.SetTlfID(tlf.NullID) 397 398 daemon := config.KeybaseService().(*KeybaseDaemonLocal) 399 daemon.AddNewAssertionForTestOrBust("bob", "bob@twitter") 400 401 config.mockMdserv.EXPECT().GetForHandle(ctx, 402 hUnresolved.ToBareHandleOrBust(), kbfsmd.Merged, nil).Return( 403 id, rmds, nil) 404 405 // Should still fail. 406 _, err = config.MDOps().GetIDForHandle(ctx, hUnresolved) 407 if _, ok := err.(tlfhandle.HandleMismatchError); !ok { 408 t.Errorf("Got unexpected error on bad handle check test: %v", err) 409 } 410 } 411 412 func testMDOpsGetIDForHandlePublicFailFindKey( 413 t *testing.T, ver kbfsmd.MetadataVer) { 414 mockCtrl, config, ctx := mdOpsInit(t, ver) 415 defer mdOpsShutdown(mockCtrl, config) 416 417 id := tlf.FakeID(1, tlf.Public) 418 h := parseTlfHandleOrBust(t, config, "alice,bob", tlf.Public, id) 419 rmds, _ := newRMDS(t, config, h) 420 h.SetTlfID(tlf.NullID) 421 422 // Do this before setting tlfHandle to nil. 423 verifyMDForPublic(config, rmds, VerifyingKeyNotFoundError{}) 424 425 config.mockMdserv.EXPECT().GetForHandle(ctx, h.ToBareHandleOrBust(), 426 kbfsmd.Merged, nil).Return(id, rmds, nil) 427 428 _, err := config.MDOps().GetIDForHandle(ctx, h) 429 if _, ok := err.(UnverifiableTlfUpdateError); !ok { 430 t.Errorf("Got unexpected error on get: %v", err) 431 } 432 } 433 434 func testMDOpsGetIDForHandlePublicFailVerify( 435 t *testing.T, ver kbfsmd.MetadataVer) { 436 mockCtrl, config, ctx := mdOpsInit(t, ver) 437 defer mdOpsShutdown(mockCtrl, config) 438 439 id := tlf.FakeID(1, tlf.Public) 440 h := parseTlfHandleOrBust(t, config, "alice,bob", tlf.Public, id) 441 rmds, _ := newRMDS(t, config, h) 442 h.SetTlfID(tlf.NullID) 443 444 // Change something in rmds that affects the computed MdID, 445 // which will then cause an MDMismatchError. 446 rmds.MD.(kbfsmd.MutableRootMetadata).SetRefBytes(100) 447 config.mockMdserv.EXPECT().GetForHandle(ctx, h.ToBareHandleOrBust(), 448 kbfsmd.Merged, nil).Return(id, rmds, nil) 449 450 _, err := config.MDOps().GetIDForHandle(ctx, h) 451 require.IsType(t, MDMismatchError{}, err) 452 } 453 454 func testMDOpsGetIDForHandleFailGet(t *testing.T, ver kbfsmd.MetadataVer) { 455 mockCtrl, config, ctx := mdOpsInit(t, ver) 456 defer mdOpsShutdown(mockCtrl, config) 457 458 id := tlf.FakeID(1, tlf.Private) 459 h := parseTlfHandleOrBust(t, config, "alice,bob", tlf.Private, id) 460 h.SetTlfID(tlf.NullID) 461 462 err := errors.New("Fake fail") 463 464 // only the get happens, no verify needed with a blank sig 465 config.mockMdserv.EXPECT().GetForHandle(ctx, h.ToBareHandleOrBust(), 466 kbfsmd.Merged, nil).Return(tlf.NullID, nil, err) 467 468 if _, err2 := config.MDOps().GetIDForHandle(ctx, h); err2 != err { 469 t.Errorf("Got bad error on get: %v", err2) 470 } 471 } 472 473 func testMDOpsGetIDForHandleFailHandleCheck( 474 t *testing.T, ver kbfsmd.MetadataVer) { 475 mockCtrl, config, ctx := mdOpsInit(t, ver) 476 defer mdOpsShutdown(mockCtrl, config) 477 478 id := tlf.FakeID(1, tlf.Private) 479 h := parseTlfHandleOrBust(t, config, "alice,bob", tlf.Private, id) 480 rmds, extra := newRMDS(t, config, h) 481 h.SetTlfID(tlf.NullID) 482 483 // Make a different handle. 484 otherH := parseTlfHandleOrBust(t, config, "alice", tlf.Private, id) 485 otherH.SetTlfID(tlf.NullID) 486 config.mockMdserv.EXPECT().GetForHandle(ctx, otherH.ToBareHandleOrBust(), 487 kbfsmd.Merged, nil).Return(id, rmds, nil) 488 expectGetKeyBundles(ctx, config, extra) 489 490 _, err := config.MDOps().GetIDForHandle(ctx, otherH) 491 if _, ok := err.(tlfhandle.HandleMismatchError); !ok { 492 t.Errorf("Got unexpected error on bad handle check test: %v", err) 493 } 494 } 495 496 func testMDOpsGetSuccess(t *testing.T, ver kbfsmd.MetadataVer) { 497 mockCtrl, config, ctx := mdOpsInit(t, ver) 498 defer mdOpsShutdown(mockCtrl, config) 499 500 id := tlf.FakeID(1, tlf.Private) 501 h := parseTlfHandleOrBust(t, config, "alice,bob", tlf.Private, id) 502 rmds, extra := newRMDS(t, config, h) 503 504 // Do this before setting tlfHandle to nil. 505 verifyMDForPrivate(config, rmds) 506 507 config.mockMdserv.EXPECT().GetForTLF(ctx, rmds.MD.TlfID(), kbfsmd.NullBranchID, 508 kbfsmd.Merged, nil).Return(rmds, nil) 509 expectGetKeyBundles(ctx, config, extra) 510 511 // Do this first, since rmds is consumed. 512 expectedMD := rmds.MD 513 rmd2, err := config.MDOps().GetForTLF(ctx, rmds.MD.TlfID(), nil) 514 require.NoError(t, err) 515 require.Equal(t, expectedMD, rmd2.bareMd) 516 } 517 518 func testMDOpsGetBlankSigFailure(t *testing.T, ver kbfsmd.MetadataVer) { 519 mockCtrl, config, ctx := mdOpsInit(t, ver) 520 defer mdOpsShutdown(mockCtrl, config) 521 522 id := tlf.FakeID(1, tlf.Private) 523 h := parseTlfHandleOrBust(t, config, "alice,bob", tlf.Private, id) 524 rmds, extra := newRMDS(t, config, h) 525 rmds.SigInfo = kbfscrypto.SignatureInfo{} 526 527 verifyMDForPrivate(config, rmds) 528 config.mockMdserv.EXPECT().GetForTLF(ctx, rmds.MD.TlfID(), kbfsmd.NullBranchID, 529 kbfsmd.Merged, nil).Return(rmds, nil) 530 expectGetKeyBundles(ctx, config, extra) 531 532 if _, err := config.MDOps().GetForTLF(ctx, rmds.MD.TlfID(), nil); err == nil { 533 t.Error("Got no error on get") 534 } 535 } 536 537 func testMDOpsGetFailGet(t *testing.T, ver kbfsmd.MetadataVer) { 538 mockCtrl, config, ctx := mdOpsInit(t, ver) 539 defer mdOpsShutdown(mockCtrl, config) 540 541 id := tlf.FakeID(1, tlf.Public) 542 err := errors.New("Fake fail") 543 544 // only the get happens, no verify needed with a blank sig 545 config.mockMdserv.EXPECT().GetForTLF(ctx, id, kbfsmd.NullBranchID, 546 kbfsmd.Merged, nil).Return(nil, err) 547 548 if _, err2 := config.MDOps().GetForTLF(ctx, id, nil); err2 != err { 549 t.Errorf("Got bad error on get: %v", err2) 550 } 551 } 552 553 func testMDOpsGetFailIDCheck(t *testing.T, ver kbfsmd.MetadataVer) { 554 mockCtrl, config, ctx := mdOpsInit(t, ver) 555 defer mdOpsShutdown(mockCtrl, config) 556 557 id := tlf.FakeID(1, tlf.Private) 558 h := parseTlfHandleOrBust(t, config, "alice,bob", tlf.Private, id) 559 rmds, extra := newRMDS(t, config, h) 560 561 id2 := tlf.FakeID(2, tlf.Public) 562 563 config.mockMdserv.EXPECT().GetForTLF(ctx, id2, kbfsmd.NullBranchID, 564 kbfsmd.Merged, nil).Return(rmds, nil) 565 expectGetKeyBundles(ctx, config, extra) 566 567 if _, err := config.MDOps().GetForTLF(ctx, id2, nil); err == nil { 568 t.Errorf("Got no error on bad id check test") 569 } 570 } 571 572 func makeRMDSRange(t *testing.T, config Config, 573 start kbfsmd.Revision, count int, prevID kbfsmd.ID) ( 574 rmdses []*RootMetadataSigned, extras []kbfsmd.ExtraMetadata) { 575 id := tlf.FakeID(1, tlf.Private) 576 h := parseTlfHandleOrBust(t, config, "alice,bob", tlf.Private, id) 577 for i := 0; i < count; i++ { 578 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 579 if err != nil { 580 t.Fatal(err) 581 } 582 583 addFakeRMDData(t, config.Codec(), rmd, h) 584 rmd.SetPrevRoot(prevID) 585 rmd.SetRevision(start + kbfsmd.Revision(i)) 586 587 ctx := context.Background() 588 589 // Encode and sign writer metadata. 590 err = rmd.bareMd.SignWriterMetadataInternally(ctx, config.Codec(), config.Crypto()) 591 require.NoError(t, err) 592 593 rmds, err := SignBareRootMetadata( 594 ctx, config.Codec(), config.Crypto(), config.Crypto(), 595 rmd.bareMd, time.Now()) 596 require.NoError(t, err) 597 currID, err := kbfsmd.MakeID(config.Codec(), rmds.MD) 598 require.NoError(t, err) 599 prevID = currID 600 rmdses = append(rmdses, rmds) 601 extras = append(extras, rmd.extra) 602 } 603 return rmdses, extras 604 } 605 606 type keyBundleMDServer struct { 607 MDServer 608 nextHead *RootMetadataSigned 609 nextGetRange []*RootMetadataSigned 610 611 nextMerkleRoot *kbfsmd.MerkleRoot 612 nextMerkleNodes [][]byte 613 nextMerkleRootSeqno keybase1.Seqno 614 615 lock sync.RWMutex 616 wkbs map[kbfsmd.TLFWriterKeyBundleID]kbfsmd.TLFWriterKeyBundleV3 617 rkbs map[kbfsmd.TLFReaderKeyBundleID]kbfsmd.TLFReaderKeyBundleV3 618 } 619 620 func makeKeyBundleMDServer(mdServer MDServer) *keyBundleMDServer { 621 return &keyBundleMDServer{ 622 MDServer: mdServer, 623 wkbs: make(map[kbfsmd.TLFWriterKeyBundleID]kbfsmd.TLFWriterKeyBundleV3), 624 rkbs: make(map[kbfsmd.TLFReaderKeyBundleID]kbfsmd.TLFReaderKeyBundleV3), 625 } 626 } 627 628 func (mds *keyBundleMDServer) putWKB( 629 id kbfsmd.TLFWriterKeyBundleID, wkb kbfsmd.TLFWriterKeyBundleV3) { 630 mds.lock.Lock() 631 defer mds.lock.Unlock() 632 mds.wkbs[id] = wkb 633 } 634 635 func (mds *keyBundleMDServer) putRKB( 636 id kbfsmd.TLFReaderKeyBundleID, rkb kbfsmd.TLFReaderKeyBundleV3) { 637 mds.lock.Lock() 638 defer mds.lock.Unlock() 639 mds.rkbs[id] = rkb 640 } 641 642 func (mds *keyBundleMDServer) processRMDSes( 643 rmds *RootMetadataSigned, extra kbfsmd.ExtraMetadata) { 644 if extraV3, ok := extra.(*kbfsmd.ExtraMetadataV3); ok { 645 mds.putWKB(rmds.MD.GetTLFWriterKeyBundleID(), extraV3.GetWriterKeyBundle()) 646 mds.putRKB(rmds.MD.GetTLFReaderKeyBundleID(), extraV3.GetReaderKeyBundle()) 647 } 648 } 649 650 func (mds *keyBundleMDServer) GetForTLF(ctx context.Context, id tlf.ID, 651 bid kbfsmd.BranchID, mStatus kbfsmd.MergeStatus, _ *keybase1.LockID) ( 652 *RootMetadataSigned, error) { 653 rmd := mds.nextHead 654 mds.nextHead = nil 655 return rmd, nil 656 } 657 658 func (mds *keyBundleMDServer) GetRange(ctx context.Context, id tlf.ID, 659 bid kbfsmd.BranchID, mStatus kbfsmd.MergeStatus, start, stop kbfsmd.Revision, 660 _ *keybase1.LockID) ([]*RootMetadataSigned, error) { 661 rmdses := mds.nextGetRange 662 mds.nextGetRange = nil 663 return rmdses, nil 664 } 665 666 func (mds *keyBundleMDServer) GetKeyBundles(ctx context.Context, tlfID tlf.ID, 667 wkbID kbfsmd.TLFWriterKeyBundleID, rkbID kbfsmd.TLFReaderKeyBundleID) ( 668 *kbfsmd.TLFWriterKeyBundleV3, *kbfsmd.TLFReaderKeyBundleV3, error) { 669 mds.lock.RLock() 670 defer mds.lock.RUnlock() 671 wkb := mds.wkbs[wkbID] 672 rkb := mds.rkbs[rkbID] 673 return &wkb, &rkb, nil 674 } 675 676 func (mds *keyBundleMDServer) FindNextMD( 677 ctx context.Context, tlfID tlf.ID, rootSeqno keybase1.Seqno) ( 678 nextKbfsRoot *kbfsmd.MerkleRoot, nextMerkleNodes [][]byte, 679 nextRootSeqno keybase1.Seqno, err error) { 680 nextKbfsRoot = mds.nextMerkleRoot 681 nextMerkleNodes = mds.nextMerkleNodes 682 nextRootSeqno = mds.nextMerkleRootSeqno 683 684 mds.nextMerkleRoot = nil 685 mds.nextMerkleNodes = nil 686 mds.nextMerkleRootSeqno = 0 687 return nextKbfsRoot, nextMerkleNodes, nextRootSeqno, nil 688 } 689 690 func testMDOpsGetRangeSuccessHelper( 691 t *testing.T, ver kbfsmd.MetadataVer, fromStart bool) { 692 mockCtrl, config, ctx := mdOpsInit(t, ver) 693 defer mdOpsShutdown(mockCtrl, config) 694 695 rmdses, extras := makeRMDSRange(t, config, 100, 5, kbfsmd.FakeID(1)) 696 697 start := kbfsmd.Revision(100) 698 stop := start + kbfsmd.Revision(len(rmdses)) 699 if fromStart { 700 start = 0 701 } 702 703 for _, rmds := range rmdses { 704 verifyMDForPrivate(config, rmds) 705 } 706 707 mdServer := makeKeyBundleMDServer(config.MDServer()) 708 config.SetMDServer(mdServer) 709 710 mdServer.nextGetRange = rmdses 711 for i, e := range extras { 712 mdServer.processRMDSes(rmdses[i], e) 713 } 714 715 // Do this first since rmdses is consumed. 716 expectedMDs := make([]kbfsmd.RootMetadata, len(rmdses)) 717 for i, rmds := range rmdses { 718 expectedMDs[i] = rmds.MD 719 } 720 rmds, err := config.MDOps().GetRange(ctx, rmdses[0].MD.TlfID(), start, stop, nil) 721 require.NoError(t, err) 722 require.Equal(t, len(rmdses), len(rmds)) 723 for i := 0; i < len(rmdses); i++ { 724 require.Equal(t, expectedMDs[i], rmds[i].bareMd) 725 } 726 } 727 728 func testMDOpsGetRangeSuccess(t *testing.T, ver kbfsmd.MetadataVer) { 729 testMDOpsGetRangeSuccessHelper(t, ver, false) 730 } 731 732 func testMDOpsGetRangeFromStartSuccess(t *testing.T, ver kbfsmd.MetadataVer) { 733 testMDOpsGetRangeSuccessHelper(t, ver, true) 734 } 735 736 func testMDOpsGetRangeFailBadPrevRoot(t *testing.T, ver kbfsmd.MetadataVer) { 737 mockCtrl, config, ctx := mdOpsInit(t, ver) 738 defer mdOpsShutdown(mockCtrl, config) 739 740 rmdses, extras := makeRMDSRange(t, config, 100, 5, kbfsmd.FakeID(1)) 741 742 rmdses[2].MD.(kbfsmd.MutableRootMetadata).SetPrevRoot(kbfsmd.FakeID(1)) 743 744 start := kbfsmd.Revision(100) 745 stop := start + kbfsmd.Revision(len(rmdses)) 746 747 // Verification is parallelized, so we have to expect at most one 748 // verification for each rmds. 749 for _, rmds := range rmdses { 750 verifyMDForPrivateHelper(config, rmds, 0, 1, false) 751 } 752 753 mdServer := makeKeyBundleMDServer(config.MDServer()) 754 config.SetMDServer(mdServer) 755 756 mdServer.nextGetRange = rmdses 757 for i, e := range extras { 758 mdServer.processRMDSes(rmdses[i], e) 759 } 760 761 _, err := config.MDOps().GetRange(ctx, rmdses[0].MD.TlfID(), start, stop, nil) 762 require.IsType(t, MDMismatchError{}, err) 763 } 764 765 type fakeMDServerPut struct { 766 MDServer 767 768 lastRmdsLock sync.Mutex 769 lastRmds *RootMetadataSigned 770 } 771 772 func (s *fakeMDServerPut) Put(ctx context.Context, rmds *RootMetadataSigned, 773 _ kbfsmd.ExtraMetadata, _ *keybase1.LockContext, _ keybase1.MDPriority) error { 774 s.lastRmdsLock.Lock() 775 defer s.lastRmdsLock.Unlock() 776 s.lastRmds = rmds 777 return nil 778 } 779 780 func (s *fakeMDServerPut) getLastRmds() *RootMetadataSigned { 781 s.lastRmdsLock.Lock() 782 defer s.lastRmdsLock.Unlock() 783 return s.lastRmds 784 } 785 786 func (s *fakeMDServerPut) Shutdown() {} 787 788 func validatePutPublicRMDS( 789 ctx context.Context, t *testing.T, ver kbfsmd.MetadataVer, config Config, 790 inputRmd kbfsmd.RootMetadata, rmds *RootMetadataSigned) { 791 // TODO: Handle private RMDS, too. 792 793 // Verify LastModifying* fields. 794 session, err := config.KBPKI().GetCurrentSession(ctx) 795 require.NoError(t, err) 796 require.Equal(t, session.UID, rmds.MD.LastModifyingWriter()) 797 require.Equal(t, session.UID, rmds.MD.GetLastModifyingUser()) 798 799 // Verify signature of WriterMetadata. 800 buf, err := rmds.MD.GetSerializedWriterMetadata(config.Codec()) 801 require.NoError(t, err) 802 err = kbfscrypto.Verify(buf, rmds.GetWriterMetadataSigInfo()) 803 require.NoError(t, err) 804 805 // Verify encoded PrivateMetadata. 806 var data PrivateMetadata 807 err = config.Codec().Decode(rmds.MD.GetSerializedPrivateMetadata(), &data) 808 require.NoError(t, err) 809 810 // Verify signature of RootMetadata. 811 buf, err = config.Codec().Encode(rmds.MD) 812 require.NoError(t, err) 813 err = kbfscrypto.Verify(buf, rmds.SigInfo) 814 require.NoError(t, err) 815 816 expectedRmd, err := inputRmd.DeepCopy(config.Codec()) 817 require.NoError(t, err) 818 819 // Overwrite written fields. 820 expectedRmd.SetLastModifyingWriter(rmds.MD.LastModifyingWriter()) 821 expectedRmd.SetLastModifyingUser(rmds.MD.GetLastModifyingUser()) 822 if ver < kbfsmd.SegregatedKeyBundlesVer { 823 expectedRmd.(*kbfsmd.RootMetadataV2).WriterMetadataSigInfo = 824 rmds.MD.(*kbfsmd.RootMetadataV2).WriterMetadataSigInfo 825 } 826 expectedRmd.SetSerializedPrivateMetadata(rmds.MD.GetSerializedPrivateMetadata()) 827 828 require.Equal(t, expectedRmd, rmds.MD) 829 } 830 831 func testMDOpsPutPublicSuccess(t *testing.T, ver kbfsmd.MetadataVer) { 832 ctx := context.Background() 833 config := MakeTestConfigOrBust(t, "alice", "bob") 834 config.SetMetadataVersion(ver) 835 defer CheckConfigAndShutdown(ctx, t, config) 836 837 config.MDServer().Shutdown() 838 var mdServer fakeMDServerPut 839 config.SetMDServer(&mdServer) 840 841 id := tlf.FakeID(1, tlf.Public) 842 h := parseTlfHandleOrBust(t, config, "alice,bob", tlf.Public, id) 843 844 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 845 require.NoError(t, err) 846 rmd.data = makeFakePrivateMetadataFuture(t).toCurrent() 847 rmd.tlfHandle = h 848 849 session, err := config.KBPKI().GetCurrentSession(ctx) 850 require.NoError(t, err) 851 _, err = config.MDOps().Put( 852 ctx, rmd, session.VerifyingKey, nil, keybase1.MDPriorityNormal, nil) 853 require.NoError(t, err) 854 855 rmds := mdServer.getLastRmds() 856 validatePutPublicRMDS(ctx, t, ver, config, rmd.bareMd, rmds) 857 } 858 859 func testMDOpsPutPrivateSuccess(t *testing.T, ver kbfsmd.MetadataVer) { 860 mockCtrl, config, ctx := mdOpsInit(t, ver) 861 defer mdOpsShutdown(mockCtrl, config) 862 863 config.SetCodec(kbfscodec.NewMsgpack()) 864 865 id := tlf.FakeID(1, tlf.Private) 866 h := parseTlfHandleOrBust(t, config, "alice,bob", tlf.Private, id) 867 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 868 require.NoError(t, err) 869 addFakeRMDData(t, config.Codec(), rmd, h) 870 871 putMDForPrivate(config, rmd) 872 873 key := kbfscrypto.MakeFakeVerifyingKeyOrBust("test key") 874 if _, err := config.MDOps().Put( 875 ctx, rmd, key, nil, keybase1.MDPriorityNormal, nil); err != nil { 876 t.Errorf("Got error on put: %v", err) 877 } 878 } 879 880 type failEncodeCodec struct { 881 kbfscodec.Codec 882 err error 883 } 884 885 func (c failEncodeCodec) Encode(obj interface{}) ([]byte, error) { 886 return nil, c.err 887 } 888 889 func testMDOpsPutFailEncode(t *testing.T, ver kbfsmd.MetadataVer) { 890 mockCtrl, config, ctx := mdOpsInit(t, ver) 891 defer mdOpsShutdown(mockCtrl, config) 892 893 id := tlf.FakeID(1, tlf.Private) 894 h := parseTlfHandleOrBust(t, config, "alice,bob", tlf.Private, id) 895 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 896 require.NoError(t, err) 897 898 expectGetTLFCryptKeyForEncryption(config, rmd) 899 config.mockCrypto.EXPECT().EncryptPrivateMetadata( 900 rmd.data, kbfscrypto.TLFCryptKey{}).Return( 901 kbfscrypto.EncryptedPrivateMetadata{}, nil) 902 config.mockBsplit.EXPECT().ShouldEmbedData(gomock.Any()).Return(true) 903 904 session, err := config.KBPKI().GetCurrentSession(ctx) 905 require.NoError(t, err) 906 907 err = errors.New("Fake fail") 908 config.SetCodec(failEncodeCodec{config.Codec(), err}) 909 910 if _, err2 := config.MDOps().Put( 911 ctx, rmd, session.VerifyingKey, nil, keybase1.MDPriorityNormal, 912 nil); err2 != err { 913 t.Errorf("Got bad error on put: %v", err2) 914 } 915 } 916 917 func testMDOpsGetRangeFailFinal(t *testing.T, ver kbfsmd.MetadataVer) { 918 mockCtrl, config, ctx := mdOpsInit(t, ver) 919 defer mdOpsShutdown(mockCtrl, config) 920 921 rmdses, extras := makeRMDSRange(t, config, 100, 5, kbfsmd.FakeID(1)) 922 rmdses[2].MD.(kbfsmd.MutableRootMetadata).SetFinalBit() 923 rmdses[2].MD.(kbfsmd.MutableRootMetadata).SetPrevRoot(rmdses[1].MD.GetPrevRoot()) 924 925 start := kbfsmd.Revision(100) 926 stop := start + kbfsmd.Revision(len(rmdses)) 927 928 // Verification is parallelized, so we have to expect at most one 929 // verification for each rmds. 930 for _, rmds := range rmdses { 931 verifyMDForPrivateHelper(config, rmds, 0, 1, false) 932 } 933 934 mdServer := makeKeyBundleMDServer(config.MDServer()) 935 config.SetMDServer(mdServer) 936 937 mdServer.nextGetRange = rmdses 938 for i, e := range extras { 939 mdServer.processRMDSes(rmdses[i], e) 940 } 941 _, err := config.MDOps().GetRange(ctx, rmdses[0].MD.TlfID(), start, stop, nil) 942 require.IsType(t, MDMismatchError{}, err) 943 } 944 945 func testMDOpsGetFinalSuccess(t *testing.T, ver kbfsmd.MetadataVer) { 946 mockCtrl, config, ctx := mdOpsInit(t, ver) 947 defer mdOpsShutdown(mockCtrl, config) 948 949 rmdses, extras := makeRMDSRange( 950 t, config, kbfsmd.RevisionInitial, 5, kbfsmd.ID{}) 951 952 now := time.Now() 953 finalizedInfo, err := tlf.NewHandleExtension( 954 tlf.HandleExtensionFinalized, 1, kbname.NormalizedUsername("<unknown>"), 955 now) 956 require.NoError(t, err) 957 finalRMDS, err := rmdses[len(rmdses)-1].MakeFinalCopy( 958 config.Codec(), now, finalizedInfo) 959 require.NoError(t, err) 960 verifyMDForPrivateHelper(config, finalRMDS, 1, 1, false) 961 962 config.SetMDCache(NewMDCacheStandard(10)) 963 mdServer := makeKeyBundleMDServer(config.MDServer()) 964 config.SetMDServer(mdServer) 965 966 // A finalized head will force MDOps to fetch the preceding MD, in 967 // order to check the authenticity of the copied writer MD. 968 // However the key that signed that MD could be a pre-reset key, 969 // so we need to make calls to get unverified keys. 970 mdServer.nextHead = finalRMDS 971 lastRMDRange := rmdses[len(rmdses)-1:] 972 mdServer.nextGetRange = lastRMDRange 973 for i, e := range extras { 974 mdServer.processRMDSes(rmdses[i], e) 975 } 976 977 verifyMDForPrivateHelper(config, lastRMDRange[0], 1, 1, true) 978 979 _, err = config.MDOps().GetForTLF(ctx, finalRMDS.MD.TlfID(), nil) 980 require.NoError(t, err) 981 } 982 983 func makeRealInitialRMDForTesting( 984 ctx context.Context, t *testing.T, config Config, h *tlfhandle.Handle, 985 id tlf.ID) (*RootMetadata, *RootMetadataSigned) { 986 rmd, err := makeInitialRootMetadata(config.MetadataVersion(), id, h) 987 require.NoError(t, err) 988 if h.TypeForKeying() == tlf.TeamKeying { 989 rmd.bareMd.SetLatestKeyGenerationForTeamTLF(1) 990 } else { 991 rekeyDone, _, err := config.KeyManager().Rekey(ctx, rmd, false) 992 require.NoError(t, err) 993 require.True(t, rekeyDone) 994 } 995 _, _, _, err = ResetRootBlock(ctx, config, rmd) 996 require.NoError(t, err) 997 session, err := config.KBPKI().GetCurrentSession(ctx) 998 require.NoError(t, err) 999 err = encryptMDPrivateData( 1000 ctx, config.Codec(), config.Crypto(), 1001 config.Crypto(), config.KeyManager(), session.UID, rmd) 1002 require.NoError(t, err) 1003 err = rmd.bareMd.SignWriterMetadataInternally( 1004 ctx, config.Codec(), config.Crypto()) 1005 require.NoError(t, err) 1006 now := config.Clock().Now() 1007 rmds, err := SignBareRootMetadata( 1008 ctx, config.Codec(), config.Crypto(), config.Crypto(), rmd.bareMd, now) 1009 require.NoError(t, err) 1010 return rmd, rmds 1011 } 1012 1013 func makeSuccessorRMDForTesting( 1014 ctx context.Context, t *testing.T, config Config, currRMD *RootMetadata, 1015 deviceToRevoke int) ( 1016 *RootMetadata, *RootMetadataSigned) { 1017 mdID, err := kbfsmd.MakeID(config.Codec(), currRMD.bareMd) 1018 require.NoError(t, err) 1019 1020 rmd, err := currRMD.MakeSuccessor( 1021 ctx, config.MetadataVersion(), config.Codec(), config.KeyManager(), 1022 config.KBPKI(), config.KBPKI(), config, mdID, true) 1023 require.NoError(t, err) 1024 1025 session, err := config.KBPKI().GetCurrentSession(ctx) 1026 require.NoError(t, err) 1027 if deviceToRevoke > 0 { 1028 RevokeDeviceForLocalUserOrBust(t, config, session.UID, deviceToRevoke) 1029 rekeyDone, _, err := config.KeyManager().Rekey(ctx, rmd, false) 1030 require.NoError(t, err) 1031 require.True(t, rekeyDone) 1032 } 1033 _, _, _, err = ResetRootBlock(ctx, config, rmd) 1034 require.NoError(t, err) 1035 err = encryptMDPrivateData( 1036 ctx, config.Codec(), config.Crypto(), 1037 config.Crypto(), config.KeyManager(), session.UID, rmd) 1038 require.NoError(t, err) 1039 1040 err = rmd.bareMd.SignWriterMetadataInternally( 1041 ctx, config.Codec(), config.Crypto()) 1042 require.NoError(t, err) 1043 now := config.Clock().Now() 1044 rmds, err := SignBareRootMetadata( 1045 ctx, config.Codec(), config.Crypto(), config.Crypto(), 1046 rmd.bareMd, now) 1047 require.NoError(t, err) 1048 return rmd, rmds 1049 } 1050 1051 func makeEncryptedMerkleLeafForTesting( 1052 t *testing.T, config Config, rmd *RootMetadata) ( 1053 root *kbfsmd.MerkleRoot, rootNodeBytes []byte, 1054 mLeaf kbfsmd.MerkleLeaf, leafBytes []byte) { 1055 ePubKey, ePrivKey, err := kbfscrypto.MakeRandomTLFEphemeralKeys() 1056 require.NoError(t, err) 1057 var nonce [24]byte 1058 _, err = rand.Read(nonce[:]) 1059 require.NoError(t, err) 1060 now := config.Clock().Now().Unix() 1061 root = &kbfsmd.MerkleRoot{ 1062 EPubKey: &ePubKey, 1063 Nonce: &nonce, 1064 Timestamp: now, 1065 } 1066 1067 mLeaf = kbfsmd.MerkleLeaf{ 1068 Revision: 1, 1069 Timestamp: now, 1070 } 1071 var pubKey kbfscrypto.TLFPublicKey 1072 if rmd.TypeForKeying() == tlf.TeamKeying { 1073 crypto, ok := config.Crypto().(*CryptoLocal) 1074 require.True(t, ok) 1075 tid := rmd.GetTlfHandle().FirstResolvedWriter().AsTeamOrBust() 1076 pubKey, err = crypto.pubKeyForTeamKeyGeneration( 1077 tid, keybase1.PerTeamKeyGeneration(rmd.LatestKeyGeneration())) 1078 require.NoError(t, err) 1079 } else { 1080 pubKey, err = rmd.bareMd.GetCurrentTLFPublicKey(rmd.extra) 1081 require.NoError(t, err) 1082 } 1083 eLeaf, err := mLeaf.Encrypt(config.Codec(), pubKey, &nonce, ePrivKey) 1084 require.NoError(t, err) 1085 leafBytes, err = config.Codec().Encode(eLeaf) 1086 require.NoError(t, err) 1087 1088 rootNode := merkle.Node{ 1089 Type: 2, 1090 Leafs: []merkle.KeyValuePair{{ 1091 Key: merkle.Hash(rmd.TlfID().Bytes()), 1092 Value: leafBytes, 1093 }}, 1094 } 1095 rootNodeBytes, err = config.Codec().Encode(rootNode) 1096 require.NoError(t, err) 1097 hasher := merkle.SHA512Hasher{} 1098 root.Hash = hasher.Hash(rootNodeBytes) 1099 1100 return root, rootNodeBytes, mLeaf, leafBytes 1101 } 1102 1103 func testMDOpsDecryptMerkleLeafPrivate(t *testing.T, ver kbfsmd.MetadataVer) { 1104 var u1 kbname.NormalizedUsername = "u1" 1105 config, _, ctx, cancel := kbfsOpsConcurInit(t, u1) 1106 defer kbfsConcurTestShutdown(ctx, t, config, cancel) 1107 config.SetMetadataVersion(ver) 1108 1109 mdServer := makeKeyBundleMDServer(config.MDServer()) 1110 config.SetMDServer(mdServer) 1111 1112 session, err := config.KBPKI().GetCurrentSession(ctx) 1113 require.NoError(t, err) 1114 var extraDevice int 1115 for i := 0; i < 4; i++ { 1116 extraDevice = AddDeviceForLocalUserOrBust(t, config, session.UID) 1117 } 1118 1119 t.Log("Making an initial RMD") 1120 id := tlf.FakeID(1, tlf.Private) 1121 h := parseTlfHandleOrBust(t, config, "u1", tlf.Private, id) 1122 rmd, rmds := makeRealInitialRMDForTesting(ctx, t, config, h, id) 1123 1124 t.Log("Making an encrypted Merkle leaf") 1125 root, _, mLeaf, leafBytes := makeEncryptedMerkleLeafForTesting( 1126 t, config, rmd) 1127 1128 mdServer.nextHead = rmds 1129 mdServer.processRMDSes(rmds, rmd.extra) 1130 1131 t.Log("Try to decrypt with the right key") 1132 mdOps := config.MDOps().(*MDOpsStandard) 1133 mLeaf2, err := mdOps.decryptMerkleLeaf(ctx, rmd.ReadOnly(), root, leafBytes) 1134 require.NoError(t, err) 1135 require.Equal(t, mLeaf.Revision, mLeaf2.Revision) 1136 require.Equal(t, mLeaf.Timestamp, mLeaf2.Timestamp) 1137 1138 // `rmds` gets destroyed by `MDOpsStandard.GetForTLF()`, so we 1139 // need to make another one. 1140 now := config.Clock().Now() 1141 rmds, err = SignBareRootMetadata( 1142 ctx, config.Codec(), config.Crypto(), config.Crypto(), rmd.bareMd, now) 1143 require.NoError(t, err) 1144 mdServer.nextHead = rmds 1145 1146 t.Log("Try to decrypt with the wrong key; should fail") 1147 _, privKeyWrong, _, err := config.Crypto().MakeRandomTLFKeys() 1148 require.NoError(t, err) 1149 privKey := rmd.data.TLFPrivateKey 1150 rmd.data.TLFPrivateKey = privKeyWrong 1151 _, err = mdOps.decryptMerkleLeaf(ctx, rmd.ReadOnly(), root, leafBytes) 1152 require.Error(t, err) 1153 1154 t.Log("Make some successors, every once in a while bumping the keygen") 1155 rmd.data.TLFPrivateKey = privKey 1156 allRMDs := []*RootMetadata{rmd} 1157 allRMDSs := []*RootMetadataSigned{rmds} 1158 for i := 2; i < 20; i++ { 1159 deviceToRevoke := -1 1160 if i%5 == 0 { 1161 deviceToRevoke = extraDevice 1162 extraDevice-- 1163 } 1164 1165 rmd, rmds = makeSuccessorRMDForTesting( 1166 ctx, t, config, rmd, deviceToRevoke) 1167 allRMDs = append(allRMDs, rmd) 1168 allRMDSs = append(allRMDSs, rmds) 1169 1170 if i%5 == 0 { 1171 mdServer.processRMDSes(rmds, rmd.extra) 1172 } 1173 } 1174 1175 t.Log("Decrypt a leaf that's encrypted with the next keygen") 1176 leafRMD := allRMDs[6] 1177 root, _, mLeaf, leafBytes = makeEncryptedMerkleLeafForTesting( 1178 t, config, leafRMD) 1179 rmds, err = SignBareRootMetadata( 1180 ctx, config.Codec(), config.Crypto(), config.Crypto(), 1181 rmd.bareMd, now) 1182 require.NoError(t, err) 1183 mdServer.nextHead = rmds 1184 mdServer.nextGetRange = allRMDSs[1:10] 1185 mLeaf2, err = mdOps.decryptMerkleLeaf( 1186 ctx, allRMDs[0].ReadOnly(), root, leafBytes) 1187 require.NoError(t, err) 1188 require.Equal(t, mLeaf.Revision, mLeaf2.Revision) 1189 require.Equal(t, mLeaf.Timestamp, mLeaf2.Timestamp) 1190 } 1191 1192 func testMDOpsDecryptMerkleLeafTeam(t *testing.T, ver kbfsmd.MetadataVer) { 1193 if ver < kbfsmd.SegregatedKeyBundlesVer { 1194 t.Skip("Teams not supported") 1195 } 1196 1197 var u1 kbname.NormalizedUsername = "u1" 1198 config, _, ctx, cancel := kbfsOpsConcurInit(t, u1) 1199 defer kbfsConcurTestShutdown(ctx, t, config, cancel) 1200 config.SetMetadataVersion(ver) 1201 1202 session, err := config.KBPKI().GetCurrentSession(ctx) 1203 require.NoError(t, err) 1204 1205 t.Log("Making an initial RMD") 1206 id := tlf.FakeID(1, tlf.SingleTeam) 1207 teamInfos := AddEmptyTeamsForTestOrBust(t, config, "t1") 1208 AddTeamWriterForTestOrBust(t, config, teamInfos[0].TID, session.UID) 1209 h := parseTlfHandleOrBust(t, config, "t1", tlf.SingleTeam, id) 1210 rmd, _ := makeRealInitialRMDForTesting(ctx, t, config, h, id) 1211 1212 t.Log("Making an encrypted Merkle leaf") 1213 root, _, mLeaf, leafBytes := makeEncryptedMerkleLeafForTesting( 1214 t, config, rmd) 1215 1216 t.Log("Try to decrypt with the right key") 1217 mdOps := config.MDOps().(*MDOpsStandard) 1218 mLeaf2, err := mdOps.decryptMerkleLeaf(ctx, rmd.ReadOnly(), root, leafBytes) 1219 require.NoError(t, err) 1220 require.Equal(t, mLeaf.Revision, mLeaf2.Revision) 1221 require.Equal(t, mLeaf.Timestamp, mLeaf2.Timestamp) 1222 1223 // Error scenarios and multiple keygens are handled by the 1224 // service, and are not worth testing here. 1225 } 1226 1227 func testMDOpsVerifyRevokedDeviceWrite(t *testing.T, ver kbfsmd.MetadataVer) { 1228 var u1 kbname.NormalizedUsername = "u1" 1229 config, _, ctx, cancel := kbfsOpsConcurInit(t, u1) 1230 defer kbfsConcurTestShutdown(ctx, t, config, cancel) 1231 config.SetMetadataVersion(ver) 1232 clock := clocktest.NewTestClockNow() 1233 config.SetClock(clock) 1234 1235 session, err := config.KBPKI().GetCurrentSession(ctx) 1236 require.NoError(t, err) 1237 config2 := ConfigAsUser(config, u1) 1238 defer CheckConfigAndShutdown(ctx, t, config2) 1239 AddDeviceForLocalUserOrBust(t, config, session.UID) 1240 extraDevice := AddDeviceForLocalUserOrBust(t, config2, session.UID) 1241 SwitchDeviceForLocalUserOrBust(t, config2, extraDevice) 1242 1243 mdServer := makeKeyBundleMDServer(config.MDServer()) 1244 config.SetMDServer(mdServer) 1245 config2.SetMDServer(mdServer) 1246 1247 t.Log("Initial MD written by the device we will revoke") 1248 id := tlf.FakeID(1, tlf.Private) 1249 h := parseTlfHandleOrBust(t, config, "u1", tlf.Private, id) 1250 rmd, rmds := makeRealInitialRMDForTesting(ctx, t, config2, h, id) 1251 mdServer.processRMDSes(rmds, rmd.extra) 1252 1253 t.Log("A few writes by a device that won't be revoked") 1254 allRMDs := []*RootMetadata{rmd} 1255 allRMDSs := []*RootMetadataSigned{rmds} 1256 for i := 2; i < 5; i++ { 1257 rmd, rmds = makeSuccessorRMDForTesting(ctx, t, config, rmd, -1) 1258 allRMDs = append(allRMDs, rmd) 1259 allRMDSs = append(allRMDSs, rmds) 1260 } 1261 1262 t.Log("A write after the revoke happens") 1263 rmd, rmds = makeSuccessorRMDForTesting(ctx, t, config, rmd, extraDevice) 1264 allRMDs = append(allRMDs, rmd) 1265 allRMDSs = append(allRMDSs, rmds) 1266 mdServer.processRMDSes(rmds, rmd.extra) 1267 mdServer.nextHead = rmds 1268 mdServer.nextGetRange = allRMDSs[1 : len(allRMDSs)-1] 1269 1270 t.Log("Make a merkle leaf using the new generation") 1271 clock.Add(1 * time.Second) 1272 root, rootNodeBytes, _, leafBytes := makeEncryptedMerkleLeafForTesting( 1273 t, config, rmd) 1274 mdServer.nextMerkleRoot = root 1275 mdServer.nextMerkleNodes = [][]byte{rootNodeBytes, leafBytes} 1276 mdServer.nextMerkleRootSeqno = 100 1277 1278 irmd := MakeImmutableRootMetadata( 1279 allRMDs[0], allRMDSs[0].SigInfo.VerifyingKey, allRMDs[1].PrevRoot(), 1280 time.Now(), false) 1281 1282 mdOps := config.MDOps().(*MDOpsStandard) 1283 cacheable, err := mdOps.verifyKey( 1284 ctx, allRMDSs[0], allRMDSs[0].MD.GetLastModifyingUser(), 1285 allRMDSs[0].SigInfo.VerifyingKey, irmd) 1286 require.NoError(t, err) 1287 require.True(t, cacheable) 1288 1289 t.Log("Make the server return no information, but within the max gap") 1290 SetGlobalMerkleRootForTestOrBust( 1291 t, config, keybase1.MerkleRootV2{}, clock.Now()) 1292 clock.Add(1 * time.Minute) 1293 mdServer.nextMerkleRoot = nil 1294 mdServer.nextMerkleNodes = nil 1295 mdServer.nextMerkleRootSeqno = 0 1296 mdLocal, ok := mdServer.MDServer.(mdServerLocal) 1297 require.True(t, ok) 1298 mdLocal.setKbfsMerkleRoot(keybase1.MerkleTreeID_KBFS_PRIVATE, root) 1299 cacheable, err = mdOps.verifyKey( 1300 ctx, allRMDSs[0], allRMDSs[0].MD.GetLastModifyingUser(), 1301 allRMDSs[0].SigInfo.VerifyingKey, irmd) 1302 require.NoError(t, err) 1303 require.True(t, cacheable) 1304 1305 t.Log("Make the server return no information, but outside the max gap") 1306 config.MDCache().(*MDCacheStandard).nextMDLRU.Purge() 1307 clock.Add(maxAllowedMerkleGap) // already added one minute above 1308 _, err = mdOps.verifyKey( 1309 ctx, allRMDSs[0], allRMDSs[0].MD.GetLastModifyingUser(), 1310 allRMDSs[0].SigInfo.VerifyingKey, irmd) 1311 require.Error(t, err) 1312 1313 t.Log("Make the server return a root, but which is outside the max gap") 1314 config.MDCache().(*MDCacheStandard).nextMDLRU.Purge() 1315 root.Timestamp = clock.Now().Unix() 1316 mdServer.nextMerkleRoot = root 1317 mdServer.nextMerkleNodes = [][]byte{leafBytes} 1318 mdServer.nextMerkleRootSeqno = 100 1319 _, err = mdOps.verifyKey( 1320 ctx, allRMDSs[0], allRMDSs[0].MD.GetLastModifyingUser(), 1321 allRMDSs[0].SigInfo.VerifyingKey, irmd) 1322 require.Error(t, err) 1323 } 1324 1325 func testMDOpsVerifyRemovedUserWrite(t *testing.T, ver kbfsmd.MetadataVer) { 1326 if ver < kbfsmd.SegregatedKeyBundlesVer { 1327 t.Skip("Teams not supported") 1328 } 1329 1330 var u1, u2 kbname.NormalizedUsername = "u1", "u2" 1331 config, _, ctx, cancel := kbfsOpsConcurInit(t, u1, u2) 1332 defer kbfsConcurTestShutdown(ctx, t, config, cancel) 1333 config.SetMetadataVersion(ver) 1334 1335 session, err := config.KBPKI().GetCurrentSession(ctx) 1336 require.NoError(t, err) 1337 1338 config2 := ConfigAsUser(config, u2) 1339 defer CheckConfigAndShutdown(ctx, t, config2) 1340 session2, err := config2.KBPKI().GetCurrentSession(ctx) 1341 require.NoError(t, err) 1342 1343 mdServer := makeKeyBundleMDServer(config.MDServer()) 1344 config.SetMDServer(mdServer) 1345 config2.SetMDServer(mdServer) 1346 1347 t.Log("Initial MD written by the user we will remove") 1348 id := tlf.FakeID(1, tlf.SingleTeam) 1349 teamInfos := AddEmptyTeamsForTestOrBust(t, config, "t1") 1350 AddEmptyTeamsForTestOrBust(t, config2, "t1") 1351 tid := teamInfos[0].TID 1352 AddTeamWriterForTestOrBust(t, config, tid, session.UID) 1353 AddTeamWriterForTestOrBust(t, config2, tid, session.UID) 1354 AddTeamWriterForTestOrBust(t, config, tid, session2.UID) 1355 AddTeamWriterForTestOrBust(t, config2, tid, session2.UID) 1356 h := parseTlfHandleOrBust(t, config, "t1", tlf.SingleTeam, id) 1357 rmd, rmds := makeRealInitialRMDForTesting(ctx, t, config, h, id) 1358 mdServer.processRMDSes(rmds, rmd.extra) 1359 1360 RemoveTeamWriterForTestOrBust(t, config, tid, session.UID) 1361 RemoveTeamWriterForTestOrBust(t, config2, tid, session.UID) 1362 1363 t.Log("A few writes by a user that won't be removed") 1364 allRMDSs := []*RootMetadataSigned{rmds} 1365 for i := 2; i < 5; i++ { 1366 rmd, rmds = makeSuccessorRMDForTesting(ctx, t, config2, rmd, -1) 1367 allRMDSs = append(allRMDSs, rmds) 1368 } 1369 1370 mdServer.processRMDSes(rmds, rmd.extra) 1371 mdServer.nextHead = rmds 1372 mdServer.nextGetRange = allRMDSs[1 : len(allRMDSs)-1] 1373 1374 t.Log("Make a merkle leaf") 1375 root, rootNodeBytes, _, leafBytes := makeEncryptedMerkleLeafForTesting( 1376 t, config, rmd) 1377 mdServer.nextMerkleRoot = root 1378 mdServer.nextMerkleNodes = [][]byte{rootNodeBytes, leafBytes} 1379 mdServer.nextMerkleRootSeqno = 100 1380 1381 mdOps := config.MDOps().(*MDOpsStandard) 1382 _, err = mdOps.processMetadata(ctx, h, allRMDSs[0], rmd.extra, nil) 1383 require.NoError(t, err) 1384 1385 t.Log("Try another write by the removed user and make sure it fails") 1386 rmd, rmds = makeSuccessorRMDForTesting(ctx, t, config, rmd, -1) 1387 mdServer.processRMDSes(rmds, rmd.extra) 1388 mdServer.nextHead = rmds 1389 mdServer.nextGetRange = nil 1390 mdServer.nextMerkleRoot = root 1391 mdServer.nextMerkleNodes = [][]byte{rootNodeBytes, leafBytes} 1392 mdServer.nextMerkleRootSeqno = 100 1393 _, err = mdOps.processMetadata(ctx, h, rmds, rmd.extra, nil) 1394 require.Error(t, err) 1395 1396 } 1397 1398 func TestMDOps(t *testing.T) { 1399 tests := []func(*testing.T, kbfsmd.MetadataVer){ 1400 testMDOpsGetIDForHandlePublicSuccess, 1401 testMDOpsGetIDForHandlePrivateSuccess, 1402 testMDOpsGetIDForUnresolvedHandlePublicSuccess, 1403 testMDOpsGetIDForUnresolvedMdHandlePublicSuccess, 1404 testMDOpsGetIDForUnresolvedHandlePublicFailure, 1405 testMDOpsGetIDForHandlePublicFailFindKey, 1406 testMDOpsGetIDForHandlePublicFailVerify, 1407 testMDOpsGetIDForHandleFailGet, 1408 testMDOpsGetIDForHandleFailHandleCheck, 1409 testMDOpsGetSuccess, 1410 testMDOpsGetBlankSigFailure, 1411 testMDOpsGetFailGet, 1412 testMDOpsGetFailIDCheck, 1413 testMDOpsGetRangeSuccess, 1414 testMDOpsGetRangeFromStartSuccess, 1415 testMDOpsGetRangeFailBadPrevRoot, 1416 testMDOpsPutPublicSuccess, 1417 testMDOpsPutPrivateSuccess, 1418 testMDOpsPutFailEncode, 1419 testMDOpsGetRangeFailFinal, 1420 testMDOpsGetFinalSuccess, 1421 testMDOpsDecryptMerkleLeafPrivate, 1422 testMDOpsDecryptMerkleLeafTeam, 1423 testMDOpsVerifyRevokedDeviceWrite, 1424 testMDOpsVerifyRemovedUserWrite, 1425 } 1426 runTestsOverMetadataVers(t, "testMDOps", tests) 1427 }