github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/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  }