github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/libkbfs/root_metadata.go (about)

     1  // Copyright 2016 Keybase Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD
     3  // license that can be found in the LICENSE file.
     4  
     5  package libkbfs
     6  
     7  import (
     8  	"fmt"
     9  	"reflect"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/keybase/client/go/kbfs/data"
    14  	"github.com/keybase/client/go/kbfs/idutil"
    15  	"github.com/keybase/client/go/kbfs/kbfscodec"
    16  	"github.com/keybase/client/go/kbfs/kbfscrypto"
    17  	"github.com/keybase/client/go/kbfs/kbfsmd"
    18  	"github.com/keybase/client/go/kbfs/libkey"
    19  	"github.com/keybase/client/go/kbfs/tlf"
    20  	"github.com/keybase/client/go/kbfs/tlfhandle"
    21  	"github.com/keybase/client/go/libkb"
    22  	"github.com/keybase/client/go/logger"
    23  	"github.com/keybase/client/go/protocol/keybase1"
    24  	"github.com/keybase/go-codec/codec"
    25  	"github.com/pkg/errors"
    26  	"golang.org/x/net/context"
    27  )
    28  
    29  // PrivateMetadata contains the portion of metadata that's secret for private
    30  // directories
    31  type PrivateMetadata struct {
    32  	// directory entry for the root directory block
    33  	Dir data.DirEntry
    34  
    35  	// m_f as described in ยง 4.1.1 of https://keybase.io/docs/crypto/kbfs.
    36  	TLFPrivateKey kbfscrypto.TLFPrivateKey
    37  	// The block changes done as part of the update that created this MD
    38  	Changes BlockChanges
    39  
    40  	// The last revision up to and including which garbage collection
    41  	// was performed on this TLF.
    42  	LastGCRevision kbfsmd.Revision `codec:"lgc"`
    43  
    44  	codec.UnknownFieldSetHandler
    45  
    46  	// When the above Changes field gets unembedded into its own
    47  	// block, we may want to temporarily keep around the old
    48  	// BlockChanges for easy reference.
    49  	cachedChanges BlockChanges
    50  }
    51  
    52  type verboseOp struct {
    53  	op
    54  	indent string
    55  }
    56  
    57  func (o verboseOp) String() string {
    58  	return o.op.StringWithRefs(o.indent)
    59  }
    60  
    61  // DumpPrivateMetadata returns a detailed dump of the given
    62  // PrivateMetadata's contents.
    63  func DumpPrivateMetadata(
    64  	codec kbfscodec.Codec, serializedPMDLength int, pmd PrivateMetadata) (string, error) {
    65  	s := fmt.Sprintf("Size: %d bytes\n", serializedPMDLength)
    66  
    67  	eq, err := kbfscodec.Equal(codec, pmd, PrivateMetadata{})
    68  	if err != nil {
    69  		return "", err
    70  	}
    71  
    72  	if eq {
    73  		s += "<Undecryptable>\n"
    74  	} else {
    75  		c := kbfsmd.DumpConfig()
    76  		// Hardcode the indent level, which depends on the
    77  		// position of the Ops list.
    78  		indent := strings.Repeat(c.Indent, 4)
    79  
    80  		var pmdCopy PrivateMetadata
    81  		err := kbfscodec.Update(codec, &pmdCopy, pmd)
    82  		if err != nil {
    83  			return "", err
    84  		}
    85  		ops := pmdCopy.Changes.Ops
    86  		for i, op := range ops {
    87  			ops[i] = verboseOp{op, indent}
    88  		}
    89  
    90  		s += c.Sdump(pmdCopy)
    91  	}
    92  	return s, nil
    93  }
    94  
    95  func (p PrivateMetadata) checkValid() error {
    96  	for i, op := range p.Changes.Ops {
    97  		err := op.checkValid()
    98  		if err != nil {
    99  			return fmt.Errorf("op[%d]=%v invalid: %v", i, op, err)
   100  		}
   101  	}
   102  	return nil
   103  }
   104  
   105  // ChangesBlockInfo returns the block info for any unembedded changes.
   106  func (p PrivateMetadata) ChangesBlockInfo() data.BlockInfo {
   107  	return p.cachedChanges.Info
   108  }
   109  
   110  // A RootMetadata is a BareRootMetadata but with a deserialized
   111  // PrivateMetadata. However, note that it is possible that the
   112  // PrivateMetadata has to be left serialized due to not having the
   113  // right keys.
   114  type RootMetadata struct {
   115  	bareMd kbfsmd.MutableRootMetadata
   116  
   117  	// ExtraMetadata currently contains key bundles for post-v2
   118  	// metadata.
   119  	extra kbfsmd.ExtraMetadata
   120  
   121  	// The plaintext, deserialized PrivateMetadata
   122  	//
   123  	// TODO: This should really be a pointer so that it's more
   124  	// clear when the data has been successfully deserialized.
   125  	data PrivateMetadata
   126  
   127  	// The TLF handle for this MD. May be nil if this object was
   128  	// deserialized (more common on the server side).
   129  	tlfHandle *tlfhandle.Handle
   130  }
   131  
   132  var _ libkey.KeyMetadata = (*RootMetadata)(nil)
   133  
   134  // makeRootMetadata makes a RootMetadata object from the given
   135  // parameters.
   136  func makeRootMetadata(bareMd kbfsmd.MutableRootMetadata,
   137  	extra kbfsmd.ExtraMetadata, handle *tlfhandle.Handle) *RootMetadata {
   138  	if bareMd == nil {
   139  		panic("nil kbfsmd.MutableRootMetadata")
   140  	}
   141  	// extra can be nil.
   142  	if handle == nil {
   143  		panic("nil handle")
   144  	}
   145  	return &RootMetadata{
   146  		bareMd:    bareMd,
   147  		extra:     extra,
   148  		tlfHandle: handle,
   149  	}
   150  }
   151  
   152  // makeInitialRootMetadata creates a new RootMetadata with the given
   153  // MetadataVer, revision RevisionInitial, and the given TLF ID
   154  // and handle. Note that if the given ID/handle are private, rekeying
   155  // must be done separately.
   156  func makeInitialRootMetadata(
   157  	ver kbfsmd.MetadataVer, tlfID tlf.ID, h *tlfhandle.Handle) (*RootMetadata, error) {
   158  	bh, err := h.ToBareHandle()
   159  	if err != nil {
   160  		return nil, err
   161  	}
   162  
   163  	bareMD, err := kbfsmd.MakeInitialRootMetadata(ver, tlfID, bh)
   164  	if err != nil {
   165  		return nil, err
   166  	}
   167  	// Need to keep the TLF handle around long enough to rekey the
   168  	// metadata for the first time.
   169  	rmd := makeRootMetadata(bareMD, nil, h)
   170  	// The initial revision never has any unrefs, so set the
   171  	// last GC revision to 1 to avoid having to walk backwards
   172  	// through all the MDs during the first QR for this TLF.
   173  	rmd.data.LastGCRevision = kbfsmd.RevisionInitial
   174  	return rmd, nil
   175  }
   176  
   177  // Data returns the private metadata of this RootMetadata.
   178  func (md *RootMetadata) Data() *PrivateMetadata {
   179  	return &md.data
   180  }
   181  
   182  // GetRootDirEntry implements the KeyMetadataWithRootDirEntry
   183  // interface for RootMetadata.
   184  func (md *RootMetadata) GetRootDirEntry() data.DirEntry {
   185  	return md.data.Dir
   186  }
   187  
   188  // Extra returns the extra metadata of this RootMetadata.
   189  func (md *RootMetadata) Extra() kbfsmd.ExtraMetadata {
   190  	return md.extra
   191  }
   192  
   193  // IsReadable returns true if the private metadata can be read.
   194  func (md *RootMetadata) IsReadable() bool {
   195  	return md.TlfID().Type() == tlf.Public || md.data.Dir.IsInitialized()
   196  }
   197  
   198  func (md *RootMetadata) clearLastRevision() {
   199  	md.ClearBlockChanges()
   200  	// remove the copied flag (if any.)
   201  	md.clearWriterMetadataCopiedBit()
   202  }
   203  
   204  func (md *RootMetadata) deepCopy(codec kbfscodec.Codec) (*RootMetadata, error) {
   205  	brmdCopy, err := md.bareMd.DeepCopy(codec)
   206  	if err != nil {
   207  		return nil, err
   208  	}
   209  
   210  	var extraCopy kbfsmd.ExtraMetadata
   211  	if md.extra != nil {
   212  		extraCopy, err = md.extra.DeepCopy(codec)
   213  		if err != nil {
   214  			return nil, err
   215  		}
   216  	}
   217  
   218  	handleCopy := md.tlfHandle.DeepCopy()
   219  
   220  	rmd := makeRootMetadata(brmdCopy, extraCopy, handleCopy)
   221  
   222  	err = kbfscodec.Update(codec, &rmd.data, md.data)
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  	err = kbfscodec.Update(
   227  		codec, &rmd.data.cachedChanges, md.data.cachedChanges)
   228  	if err != nil {
   229  		return nil, err
   230  	}
   231  
   232  	// Preserve all the final op paths in the copy.
   233  	for i, op := range md.data.Changes.Ops {
   234  		rmd.data.Changes.Ops[i].setFinalPath(op.getFinalPath())
   235  	}
   236  
   237  	return rmd, nil
   238  }
   239  
   240  // MakeSuccessor returns a complete copy of this RootMetadata (but
   241  // with cleared block change lists and cleared serialized metadata),
   242  // with the revision incremented and a correct backpointer.
   243  func (md *RootMetadata) MakeSuccessor(
   244  	ctx context.Context, latestMDVer kbfsmd.MetadataVer, codec kbfscodec.Codec,
   245  	keyManager KeyManager, merkleGetter idutil.MerkleRootGetter,
   246  	teamKeyer teamKeysGetter, osg idutil.OfflineStatusGetter, mdID kbfsmd.ID,
   247  	isWriter bool) (*RootMetadata, error) {
   248  	if mdID == (kbfsmd.ID{}) {
   249  		return nil, errors.New("Empty MdID in MakeSuccessor")
   250  	}
   251  	if md.IsFinal() {
   252  		return nil, kbfsmd.MetadataIsFinalError{}
   253  	}
   254  
   255  	isReadableAndWriter := md.IsReadable() && isWriter
   256  
   257  	brmdCopy, extraCopy, err := md.bareMd.MakeSuccessorCopy(
   258  		codec, md.extra, latestMDVer,
   259  		func() ([]kbfscrypto.TLFCryptKey, error) {
   260  			return keyManager.GetTLFCryptKeyOfAllGenerations(ctx, md)
   261  		}, isReadableAndWriter)
   262  	if err != nil {
   263  		return nil, err
   264  	}
   265  
   266  	handleCopy := md.tlfHandle.DeepCopy()
   267  
   268  	newMd := makeRootMetadata(brmdCopy, extraCopy, handleCopy)
   269  	if err := kbfscodec.Update(codec, &newMd.data, md.data); err != nil {
   270  		return nil, err
   271  	}
   272  
   273  	if isReadableAndWriter {
   274  		newMd.clearLastRevision()
   275  		// clear the serialized data.
   276  		newMd.SetSerializedPrivateMetadata(nil)
   277  		if newMd.TypeForKeying() == tlf.TeamKeying {
   278  			tid, err := handleCopy.FirstResolvedWriter().AsTeam()
   279  			if err != nil {
   280  				return nil, err
   281  			}
   282  
   283  			offline := keybase1.OfflineAvailability_NONE
   284  			if osg != nil {
   285  				offline = osg.OfflineAvailabilityForID(md.TlfID())
   286  			}
   287  
   288  			_, keyGen, err := teamKeyer.GetTeamTLFCryptKeys(
   289  				ctx, tid, kbfsmd.UnspecifiedKeyGen, offline)
   290  			if err != nil {
   291  				return nil, err
   292  			}
   293  			newMd.bareMd.SetLatestKeyGenerationForTeamTLF(keyGen)
   294  		}
   295  	} else {
   296  		// if we can't read it it means we're simply setting the rekey bit
   297  		// and copying the previous data.
   298  		newMd.SetRekeyBit()
   299  		newMd.SetWriterMetadataCopiedBit()
   300  	}
   301  
   302  	newMd.SetPrevRoot(mdID)
   303  	// bump revision
   304  	if md.Revision() < kbfsmd.RevisionInitial {
   305  		return nil, errors.New("MD with invalid revision")
   306  	}
   307  	newMd.SetRevision(md.Revision() + 1)
   308  	return newMd, nil
   309  }
   310  
   311  // MakeSuccessorWithNewHandle does the same thing as MakeSuccessor,
   312  // plus it changes the handle.  (The caller is responsible for
   313  // ensuring that the handle change is valid.)
   314  func (md *RootMetadata) MakeSuccessorWithNewHandle(
   315  	ctx context.Context, newHandle *tlfhandle.Handle, latestMDVer kbfsmd.MetadataVer,
   316  	codec kbfscodec.Codec, keyManager KeyManager,
   317  	merkleGetter idutil.MerkleRootGetter, teamKeyer teamKeysGetter,
   318  	osg idutil.OfflineStatusGetter, mdID kbfsmd.ID, isWriter bool) (
   319  	*RootMetadata, error) {
   320  	mdCopy, err := md.deepCopy(codec)
   321  	if err != nil {
   322  		return nil, err
   323  	}
   324  
   325  	mdCopy.extra = nil
   326  	mdCopy.tlfHandle = newHandle.DeepCopy()
   327  	mdCopy.SetWriters(newHandle.ResolvedWriters())
   328  	// Readers are not tracked explicitly in the MD, but their key
   329  	// bundles are cleared out with the `ClearForV4Migration()` call
   330  	// below.
   331  	mdCopy.SetUnresolvedWriters(newHandle.UnresolvedWriters())
   332  	mdCopy.SetUnresolvedReaders(newHandle.UnresolvedReaders())
   333  	mdCopy.bareMd.ClearForV4Migration()
   334  
   335  	return mdCopy.MakeSuccessor(
   336  		ctx, latestMDVer, codec, keyManager, merkleGetter, teamKeyer, osg,
   337  		mdID, isWriter)
   338  }
   339  
   340  // GetTlfHandle returns the TlfHandle for this RootMetadata.
   341  func (md *RootMetadata) GetTlfHandle() *tlfhandle.Handle {
   342  	if md.tlfHandle == nil {
   343  		panic(fmt.Sprintf("RootMetadata %v with no handle", md))
   344  	}
   345  
   346  	return md.tlfHandle
   347  }
   348  
   349  // TypeForKeying returns the keying type for the RootMetadata.
   350  func (md *RootMetadata) TypeForKeying() tlf.KeyingType {
   351  	return md.bareMd.TypeForKeying()
   352  }
   353  
   354  // MakeBareTlfHandle makes a BareTlfHandle for this
   355  // RootMetadata. Should be used only by servers and MDOps.
   356  func (md *RootMetadata) MakeBareTlfHandle() (tlf.Handle, error) {
   357  	if md.tlfHandle != nil {
   358  		panic(errors.New("MakeBareTlfHandle called when md.tlfHandle exists"))
   359  	}
   360  
   361  	return md.bareMd.MakeBareTlfHandle(md.extra)
   362  }
   363  
   364  // IsInitialized returns whether or not this RootMetadata has been initialized
   365  func (md *RootMetadata) IsInitialized() bool {
   366  	keyGen := md.LatestKeyGeneration()
   367  	if md.TypeForKeying() == tlf.PublicKeying {
   368  		return keyGen == kbfsmd.PublicKeyGen
   369  	}
   370  	// The data is only initialized once we have at least one set of keys
   371  	return keyGen >= kbfsmd.FirstValidKeyGen
   372  }
   373  
   374  // AddRefBlock adds the newly-referenced block to the add block change list.
   375  func (md *RootMetadata) AddRefBlock(info data.BlockInfo) {
   376  	md.AddRefBytes(uint64(info.EncodedSize))
   377  	md.AddDiskUsage(uint64(info.EncodedSize))
   378  	md.data.Changes.AddRefBlock(info.BlockPointer)
   379  }
   380  
   381  // AddUnrefBlock adds the newly-unreferenced block to the add block change list.
   382  func (md *RootMetadata) AddUnrefBlock(info data.BlockInfo) {
   383  	if info.EncodedSize > 0 {
   384  		md.AddUnrefBytes(uint64(info.EncodedSize))
   385  		md.SetDiskUsage(md.DiskUsage() - uint64(info.EncodedSize))
   386  		md.data.Changes.AddUnrefBlock(info.BlockPointer)
   387  	}
   388  }
   389  
   390  // AddUpdate adds the newly-updated block to the add block change list.
   391  func (md *RootMetadata) AddUpdate(oldInfo data.BlockInfo, newInfo data.BlockInfo) {
   392  	md.AddUnrefBytes(uint64(oldInfo.EncodedSize))
   393  	md.AddRefBytes(uint64(newInfo.EncodedSize))
   394  	md.AddDiskUsage(uint64(newInfo.EncodedSize))
   395  	md.SetDiskUsage(md.DiskUsage() - uint64(oldInfo.EncodedSize))
   396  	md.data.Changes.AddUpdate(oldInfo.BlockPointer, newInfo.BlockPointer)
   397  }
   398  
   399  // AddOp starts a new operation for this MD update.  Subsequent
   400  // AddRefBlock, AddUnrefBlock, and AddUpdate calls will be applied to
   401  // this operation.
   402  func (md *RootMetadata) AddOp(o op) {
   403  	md.data.Changes.AddOp(o)
   404  }
   405  
   406  // ClearBlockChanges resets the block change lists to empty for this
   407  // RootMetadata.
   408  func (md *RootMetadata) ClearBlockChanges() {
   409  	md.SetRefBytes(0)
   410  	md.SetUnrefBytes(0)
   411  	md.SetMDRefBytes(0)
   412  	md.data.Changes.sizeEstimate = 0
   413  	md.data.Changes.Info = data.BlockInfo{}
   414  	md.data.Changes.Ops = nil
   415  }
   416  
   417  // SetLastGCRevision sets the last revision up to and including which
   418  // garbage collection was performed on this TLF.
   419  func (md *RootMetadata) SetLastGCRevision(rev kbfsmd.Revision) {
   420  	md.data.LastGCRevision = rev
   421  }
   422  
   423  // updateFromTlfHandle updates the current RootMetadata's fields to
   424  // reflect the given handle, which must be the result of running the
   425  // current handle with ResolveAgain().
   426  func (md *RootMetadata) updateFromTlfHandle(newHandle *tlfhandle.Handle) error {
   427  	// TODO: Strengthen check, e.g. make sure every writer/reader
   428  	// in the old handle is also a writer/reader of the new
   429  	// handle.
   430  	newBareHandle, err := newHandle.ToBareHandle()
   431  	if err != nil {
   432  		return err
   433  	}
   434  	var valid bool
   435  	switch md.TypeForKeying() {
   436  	case tlf.PrivateKeying:
   437  		// Private-keyed TLFs can move to team keying, but not to
   438  		// public keying.
   439  		valid = newBareHandle.TypeForKeying() != tlf.PublicKeying
   440  	case tlf.PublicKeying:
   441  		// Public-keyed TLFs can move to team keying, but not to
   442  		// private keying.
   443  		valid = newBareHandle.TypeForKeying() != tlf.PrivateKeying
   444  	case tlf.TeamKeying:
   445  		// Team-keyed TLFs must always remain team-keyed.
   446  		valid = newBareHandle.TypeForKeying() == tlf.TeamKeying
   447  	default:
   448  		return fmt.Errorf("Unexpected keying type %s", md.TypeForKeying())
   449  	}
   450  	if !valid {
   451  		return fmt.Errorf(
   452  			"Trying to update rmd with id type=%s, keying type=%s with "+
   453  				"handle of type=%s, keying type=%s",
   454  			md.TlfID().Type(), md.TypeForKeying(),
   455  			newHandle.Type(), newBareHandle.TypeForKeying())
   456  	}
   457  
   458  	if newBareHandle.TypeForKeying() == tlf.PrivateKeying {
   459  		md.SetUnresolvedReaders(newHandle.UnresolvedReaders())
   460  	} else {
   461  		md.SetWriters(newHandle.ResolvedWriters())
   462  	}
   463  
   464  	md.SetUnresolvedWriters(newHandle.UnresolvedWriters())
   465  	md.SetConflictInfo(newHandle.ConflictInfo())
   466  	md.SetFinalizedInfo(newHandle.FinalizedInfo())
   467  
   468  	bareHandle, err := md.bareMd.MakeBareTlfHandle(md.extra)
   469  	if err != nil {
   470  		return err
   471  	}
   472  
   473  	if !reflect.DeepEqual(bareHandle, newBareHandle) {
   474  		return fmt.Errorf(
   475  			"bareHandle=%+v != newBareHandle=%+v",
   476  			bareHandle, newBareHandle)
   477  	}
   478  
   479  	md.tlfHandle = newHandle
   480  	return nil
   481  }
   482  
   483  // loadCachedBlockChanges swaps any cached block changes so that
   484  // future local accesses to this MD (from the cache) can directly
   485  // access the ops without needing to re-embed the block changes.
   486  // Possibly copies the MD, returns the copy if so, and whether copied.
   487  func (md *RootMetadata) loadCachedBlockChanges(
   488  	ctx context.Context, bps data.BlockPutState, log logger.Logger,
   489  	vlog *libkb.VDebugLog, codec kbfscodec.Codec) (*RootMetadata, error) {
   490  	if md.data.Changes.Ops != nil || len(md.data.cachedChanges.Ops) == 0 {
   491  		return md, nil
   492  	}
   493  	md, err := md.deepCopy(codec)
   494  	if err != nil {
   495  		return nil, err
   496  	}
   497  
   498  	md.data.Changes, md.data.cachedChanges =
   499  		md.data.cachedChanges, md.data.Changes
   500  
   501  	// We always add the ref blocks to the first operation in the MD
   502  	// update.  Most MD updates will only have one op anyway, and for
   503  	// those that have more (like conflict resolution), it is
   504  	// arbitrary which one lists them as references, so putting them
   505  	// in the first op is the easiest thing to do.
   506  	md.data.Changes.Ops[0].
   507  		AddRefBlock(md.data.cachedChanges.Info.BlockPointer)
   508  	// Find the block and ref any children, if any.
   509  	if bps == nil {
   510  		panic("Must provide blocks when changes are unembedded")
   511  	}
   512  
   513  	// Prepare a map of all FileBlocks for easy access by fileData
   514  	// below.
   515  	fileBlocks := make(map[data.BlockPointer]*data.FileBlock)
   516  	for _, ptr := range bps.Ptrs() {
   517  		if block, err := bps.GetBlock(ctx, ptr); err == nil {
   518  			if fblock, ok := block.(*data.FileBlock); ok {
   519  				fileBlocks[ptr] = fblock
   520  			}
   521  		}
   522  	}
   523  
   524  	// uid, crypto and bsplitter aren't used for simply getting the
   525  	// indirect pointers, so set them to nil.
   526  	var id keybase1.UserOrTeamID
   527  	file := data.Path{
   528  		FolderBranch: data.FolderBranch{
   529  			Tlf: md.TlfID(), Branch: data.MasterBranch},
   530  		Path: []data.PathNode{{
   531  			BlockPointer: md.data.cachedChanges.Info.BlockPointer,
   532  			Name: data.NewPathPartString(
   533  				fmt.Sprintf("<MD with revision %d>", md.Revision()), nil),
   534  		}},
   535  	}
   536  	fd := data.NewFileData(file, id, nil, md.ReadOnly(),
   537  		func(_ context.Context, _ libkey.KeyMetadata, ptr data.BlockPointer,
   538  			_ data.Path, _ data.BlockReqType) (*data.FileBlock, bool, error) {
   539  			fblock, ok := fileBlocks[ptr]
   540  			if !ok {
   541  				return nil, false, fmt.Errorf(
   542  					"No unembedded block change pointer %v in bps", ptr)
   543  			}
   544  			return fblock, false, nil
   545  		},
   546  		func(_ context.Context, ptr data.BlockPointer, block data.Block) error {
   547  			return nil
   548  		}, log, vlog)
   549  
   550  	infos, err := fd.GetIndirectFileBlockInfos(ctx)
   551  	if err != nil {
   552  		return nil, err
   553  	}
   554  
   555  	for _, info := range infos {
   556  		md.data.Changes.Ops[0].AddRefBlock(info.BlockPointer)
   557  	}
   558  	return md, nil
   559  }
   560  
   561  // GetTLFCryptKeyParams wraps the respective method of the underlying BareRootMetadata for convenience.
   562  func (md *RootMetadata) GetTLFCryptKeyParams(
   563  	keyGen kbfsmd.KeyGen, user keybase1.UID, key kbfscrypto.CryptPublicKey) (
   564  	kbfscrypto.TLFEphemeralPublicKey, kbfscrypto.EncryptedTLFCryptKeyClientHalf,
   565  	kbfscrypto.TLFCryptKeyServerHalfID, bool, error) {
   566  	return md.bareMd.GetTLFCryptKeyParams(keyGen, user, key, md.extra)
   567  }
   568  
   569  // KeyGenerationsToUpdate wraps the respective method of the underlying BareRootMetadata for convenience.
   570  func (md *RootMetadata) KeyGenerationsToUpdate() (kbfsmd.KeyGen, kbfsmd.KeyGen) {
   571  	return md.bareMd.KeyGenerationsToUpdate()
   572  }
   573  
   574  // LatestKeyGeneration wraps the respective method of the underlying BareRootMetadata for convenience.
   575  func (md *RootMetadata) LatestKeyGeneration() kbfsmd.KeyGen {
   576  	return md.bareMd.LatestKeyGeneration()
   577  }
   578  
   579  // TlfID wraps the respective method of the underlying BareRootMetadata for convenience.
   580  func (md *RootMetadata) TlfID() tlf.ID {
   581  	if md == nil || md.bareMd == nil {
   582  		return tlf.NullID
   583  	}
   584  	return md.bareMd.TlfID()
   585  }
   586  
   587  // LastModifyingWriter wraps the respective method of the underlying BareRootMetadata for convenience.
   588  func (md *RootMetadata) LastModifyingWriter() keybase1.UID {
   589  	return md.bareMd.LastModifyingWriter()
   590  }
   591  
   592  // LastModifyingUser wraps the respective method of the underlying BareRootMetadata for convenience.
   593  func (md *RootMetadata) LastModifyingUser() keybase1.UID {
   594  	return md.bareMd.GetLastModifyingUser()
   595  }
   596  
   597  // RefBytes wraps the respective method of the underlying BareRootMetadata for convenience.
   598  func (md *RootMetadata) RefBytes() uint64 {
   599  	return md.bareMd.RefBytes()
   600  }
   601  
   602  // UnrefBytes wraps the respective method of the underlying BareRootMetadata for convenience.
   603  func (md *RootMetadata) UnrefBytes() uint64 {
   604  	return md.bareMd.UnrefBytes()
   605  }
   606  
   607  // MDRefBytes wraps the respective method of the underlying BareRootMetadata for convenience.
   608  func (md *RootMetadata) MDRefBytes() uint64 {
   609  	return md.bareMd.MDRefBytes()
   610  }
   611  
   612  // DiskUsage wraps the respective method of the underlying BareRootMetadata for convenience.
   613  func (md *RootMetadata) DiskUsage() uint64 {
   614  	return md.bareMd.DiskUsage()
   615  }
   616  
   617  // MDDiskUsage wraps the respective method of the underlying BareRootMetadata for convenience.
   618  func (md *RootMetadata) MDDiskUsage() uint64 {
   619  	return md.bareMd.MDDiskUsage()
   620  }
   621  
   622  // SetRefBytes wraps the respective method of the underlying BareRootMetadata for convenience.
   623  func (md *RootMetadata) SetRefBytes(refBytes uint64) {
   624  	md.bareMd.SetRefBytes(refBytes)
   625  }
   626  
   627  // SetUnrefBytes wraps the respective method of the underlying BareRootMetadata for convenience.
   628  func (md *RootMetadata) SetUnrefBytes(unrefBytes uint64) {
   629  	md.bareMd.SetUnrefBytes(unrefBytes)
   630  }
   631  
   632  // SetMDRefBytes wraps the respective method of the underlying BareRootMetadata for convenience.
   633  func (md *RootMetadata) SetMDRefBytes(mdRefBytes uint64) {
   634  	md.bareMd.SetMDRefBytes(mdRefBytes)
   635  }
   636  
   637  // SetDiskUsage wraps the respective method of the underlying BareRootMetadata for convenience.
   638  func (md *RootMetadata) SetDiskUsage(diskUsage uint64) {
   639  	md.bareMd.SetDiskUsage(diskUsage)
   640  }
   641  
   642  // SetMDDiskUsage wraps the respective method of the underlying BareRootMetadata for convenience.
   643  func (md *RootMetadata) SetMDDiskUsage(mdDiskUsage uint64) {
   644  	md.bareMd.SetMDDiskUsage(mdDiskUsage)
   645  }
   646  
   647  // AddRefBytes wraps the respective method of the underlying BareRootMetadata for convenience.
   648  func (md *RootMetadata) AddRefBytes(refBytes uint64) {
   649  	md.bareMd.AddRefBytes(refBytes)
   650  }
   651  
   652  // AddUnrefBytes wraps the respective method of the underlying BareRootMetadata for convenience.
   653  func (md *RootMetadata) AddUnrefBytes(unrefBytes uint64) {
   654  	md.bareMd.AddUnrefBytes(unrefBytes)
   655  }
   656  
   657  // AddMDRefBytes wraps the respective method of the underlying BareRootMetadata for convenience.
   658  func (md *RootMetadata) AddMDRefBytes(mdRefBytes uint64) {
   659  	md.bareMd.AddMDRefBytes(mdRefBytes)
   660  }
   661  
   662  // AddDiskUsage wraps the respective method of the underlying BareRootMetadata for convenience.
   663  func (md *RootMetadata) AddDiskUsage(diskUsage uint64) {
   664  	md.bareMd.AddDiskUsage(diskUsage)
   665  }
   666  
   667  // AddMDDiskUsage wraps the respective method of the underlying BareRootMetadata for convenience.
   668  func (md *RootMetadata) AddMDDiskUsage(mdDiskUsage uint64) {
   669  	md.bareMd.AddMDDiskUsage(mdDiskUsage)
   670  }
   671  
   672  // IsWriterMetadataCopiedSet wraps the respective method of the underlying BareRootMetadata for convenience.
   673  func (md *RootMetadata) IsWriterMetadataCopiedSet() bool {
   674  	return md.bareMd.IsWriterMetadataCopiedSet()
   675  }
   676  
   677  // IsRekeySet wraps the respective method of the underlying BareRootMetadata for convenience.
   678  func (md *RootMetadata) IsRekeySet() bool {
   679  	return md.bareMd.IsRekeySet()
   680  }
   681  
   682  // IsUnmergedSet wraps the respective method of the underlying BareRootMetadata for convenience.
   683  func (md *RootMetadata) IsUnmergedSet() bool {
   684  	return md.bareMd.IsUnmergedSet()
   685  }
   686  
   687  // Revision wraps the respective method of the underlying BareRootMetadata for convenience.
   688  func (md *RootMetadata) Revision() kbfsmd.Revision {
   689  	return md.bareMd.RevisionNumber()
   690  }
   691  
   692  // MergedStatus wraps the respective method of the underlying BareRootMetadata for convenience.
   693  func (md *RootMetadata) MergedStatus() kbfsmd.MergeStatus {
   694  	return md.bareMd.MergedStatus()
   695  }
   696  
   697  // BID wraps the respective method of the underlying BareRootMetadata for convenience.
   698  func (md *RootMetadata) BID() kbfsmd.BranchID {
   699  	return md.bareMd.BID()
   700  }
   701  
   702  // PrevRoot wraps the respective method of the underlying BareRootMetadata for convenience.
   703  func (md *RootMetadata) PrevRoot() kbfsmd.ID {
   704  	return md.bareMd.GetPrevRoot()
   705  }
   706  
   707  // Version returns the underlying BareRootMetadata version.
   708  func (md *RootMetadata) Version() kbfsmd.MetadataVer {
   709  	return md.bareMd.Version()
   710  }
   711  
   712  func (md *RootMetadata) clearRekeyBit() {
   713  	md.bareMd.ClearRekeyBit()
   714  }
   715  
   716  func (md *RootMetadata) clearWriterMetadataCopiedBit() {
   717  	md.bareMd.ClearWriterMetadataCopiedBit()
   718  }
   719  
   720  // SetUnmerged wraps the respective method of the underlying BareRootMetadata for convenience.
   721  func (md *RootMetadata) SetUnmerged() {
   722  	md.bareMd.SetUnmerged()
   723  }
   724  
   725  // SetBranchID wraps the respective method of the underlying BareRootMetadata for convenience.
   726  func (md *RootMetadata) SetBranchID(bid kbfsmd.BranchID) {
   727  	md.bareMd.SetBranchID(bid)
   728  }
   729  
   730  // SetPrevRoot wraps the respective method of the underlying BareRootMetadata for convenience.
   731  func (md *RootMetadata) SetPrevRoot(mdID kbfsmd.ID) {
   732  	md.bareMd.SetPrevRoot(mdID)
   733  }
   734  
   735  // GetSerializedPrivateMetadata wraps the respective method of the underlying BareRootMetadata for convenience.
   736  func (md *RootMetadata) GetSerializedPrivateMetadata() []byte {
   737  	return md.bareMd.GetSerializedPrivateMetadata()
   738  }
   739  
   740  // GetSerializedWriterMetadata wraps the respective method of the underlying BareRootMetadata for convenience.
   741  func (md *RootMetadata) GetSerializedWriterMetadata(
   742  	codec kbfscodec.Codec) ([]byte, error) {
   743  	return md.bareMd.GetSerializedWriterMetadata(codec)
   744  }
   745  
   746  // IsFinal wraps the respective method of the underlying BareRootMetadata for convenience.
   747  func (md *RootMetadata) IsFinal() bool {
   748  	return md.bareMd.IsFinal()
   749  }
   750  
   751  // SetSerializedPrivateMetadata wraps the respective method of the underlying BareRootMetadata for convenience.
   752  func (md *RootMetadata) SetSerializedPrivateMetadata(spmd []byte) {
   753  	md.bareMd.SetSerializedPrivateMetadata(spmd)
   754  }
   755  
   756  // SetRekeyBit wraps the respective method of the underlying BareRootMetadata for convenience.
   757  func (md *RootMetadata) SetRekeyBit() {
   758  	md.bareMd.SetRekeyBit()
   759  }
   760  
   761  // SetFinalBit wraps the respective method of the underlying BareRootMetadata for convenience.
   762  func (md *RootMetadata) SetFinalBit() {
   763  	md.bareMd.SetFinalBit()
   764  }
   765  
   766  // SetWriterMetadataCopiedBit wraps the respective method of the underlying BareRootMetadata for convenience.
   767  func (md *RootMetadata) SetWriterMetadataCopiedBit() {
   768  	md.bareMd.SetWriterMetadataCopiedBit()
   769  }
   770  
   771  // SetRevision wraps the respective method of the underlying BareRootMetadata for convenience.
   772  func (md *RootMetadata) SetRevision(revision kbfsmd.Revision) {
   773  	md.bareMd.SetRevision(revision)
   774  }
   775  
   776  // SetWriters wraps the respective method of the underlying BareRootMetadata for convenience.
   777  func (md *RootMetadata) SetWriters(writers []keybase1.UserOrTeamID) {
   778  	md.bareMd.SetWriters(writers)
   779  }
   780  
   781  // SetUnresolvedReaders wraps the respective method of the underlying BareRootMetadata for convenience.
   782  func (md *RootMetadata) SetUnresolvedReaders(readers []keybase1.SocialAssertion) {
   783  	md.bareMd.SetUnresolvedReaders(readers)
   784  }
   785  
   786  // SetUnresolvedWriters wraps the respective method of the underlying BareRootMetadata for convenience.
   787  func (md *RootMetadata) SetUnresolvedWriters(writers []keybase1.SocialAssertion) {
   788  	md.bareMd.SetUnresolvedWriters(writers)
   789  }
   790  
   791  // SetConflictInfo wraps the respective method of the underlying BareRootMetadata for convenience.
   792  func (md *RootMetadata) SetConflictInfo(ci *tlf.HandleExtension) {
   793  	md.bareMd.SetConflictInfo(ci)
   794  }
   795  
   796  // SetFinalizedInfo wraps the respective method of the underlying BareRootMetadata for convenience.
   797  func (md *RootMetadata) SetFinalizedInfo(fi *tlf.HandleExtension) {
   798  	md.bareMd.SetFinalizedInfo(fi)
   799  }
   800  
   801  // SetLastModifyingWriter wraps the respective method of the underlying BareRootMetadata for convenience.
   802  func (md *RootMetadata) SetLastModifyingWriter(user keybase1.UID) {
   803  	md.bareMd.SetLastModifyingWriter(user)
   804  }
   805  
   806  // SetLastModifyingUser wraps the respective method of the underlying BareRootMetadata for convenience.
   807  func (md *RootMetadata) SetLastModifyingUser(user keybase1.UID) {
   808  	md.bareMd.SetLastModifyingUser(user)
   809  }
   810  
   811  // SetTlfID wraps the respective method of the underlying BareRootMetadata for convenience.
   812  func (md *RootMetadata) SetTlfID(tlf tlf.ID) {
   813  	md.bareMd.SetTlfID(tlf)
   814  }
   815  
   816  // HasKeyForUser wraps the respective method of the underlying BareRootMetadata for convenience.
   817  func (md *RootMetadata) HasKeyForUser(user keybase1.UID) (
   818  	bool, error) {
   819  	writers, readers, err := md.bareMd.GetUserDevicePublicKeys(md.extra)
   820  	if err != nil {
   821  		return false, err
   822  	}
   823  	return len(writers[user]) > 0 || len(readers[user]) > 0, nil
   824  }
   825  
   826  // fakeInitialRekey wraps the FakeInitialRekey test function for
   827  // convenience.
   828  func (md *RootMetadata) fakeInitialRekey() {
   829  	bh, err := md.tlfHandle.ToBareHandle()
   830  	if err != nil {
   831  		panic(err)
   832  	}
   833  	md.extra = kbfsmd.FakeInitialRekey(md.bareMd, bh, kbfscrypto.TLFPublicKey{})
   834  }
   835  
   836  // GetBareRootMetadata returns an interface to the underlying serializeable metadata.
   837  func (md *RootMetadata) GetBareRootMetadata() kbfsmd.RootMetadata {
   838  	return md.bareMd
   839  }
   840  
   841  // AddKeyGeneration adds a new key generation to this revision of metadata.
   842  func (md *RootMetadata) AddKeyGeneration(codec kbfscodec.Codec,
   843  	wKeys, rKeys kbfsmd.UserDevicePublicKeys,
   844  	ePubKey kbfscrypto.TLFEphemeralPublicKey,
   845  	ePrivKey kbfscrypto.TLFEphemeralPrivateKey,
   846  	pubKey kbfscrypto.TLFPublicKey,
   847  	privKey kbfscrypto.TLFPrivateKey,
   848  	currCryptKey, nextCryptKey kbfscrypto.TLFCryptKey) (
   849  	serverHalves kbfsmd.UserDeviceKeyServerHalves, err error) {
   850  	nextExtra, serverHalves, err := md.bareMd.AddKeyGeneration(
   851  		codec, md.extra, wKeys, rKeys, ePubKey, ePrivKey,
   852  		pubKey, currCryptKey, nextCryptKey)
   853  	if err != nil {
   854  		return nil, err
   855  	}
   856  	md.extra = nextExtra
   857  	md.data.TLFPrivateKey = privKey
   858  	return serverHalves, nil
   859  }
   860  
   861  func (md *RootMetadata) promoteReaders(
   862  	readersToPromote map[keybase1.UID]bool) error {
   863  	return md.bareMd.PromoteReaders(readersToPromote, md.extra)
   864  }
   865  
   866  func (md *RootMetadata) revokeRemovedDevices(
   867  	wKeys, rKeys kbfsmd.UserDevicePublicKeys) (
   868  	kbfsmd.ServerHalfRemovalInfo, error) {
   869  	return md.bareMd.RevokeRemovedDevices(wKeys, rKeys, md.extra)
   870  }
   871  
   872  func (md *RootMetadata) updateKeyBundles(
   873  	codec kbfscodec.Codec, wKeys, rKeys kbfsmd.UserDevicePublicKeys,
   874  	ePubKey kbfscrypto.TLFEphemeralPublicKey,
   875  	ePrivKey kbfscrypto.TLFEphemeralPrivateKey,
   876  	tlfCryptKeys []kbfscrypto.TLFCryptKey) (
   877  	[]kbfsmd.UserDeviceKeyServerHalves, error) {
   878  	return md.bareMd.UpdateKeyBundles(codec, md.extra,
   879  		wKeys, rKeys, ePubKey, ePrivKey, tlfCryptKeys)
   880  }
   881  
   882  func (md *RootMetadata) finalizeRekey(codec kbfscodec.Codec) error {
   883  	return md.bareMd.FinalizeRekey(codec, md.extra)
   884  }
   885  
   886  func (md *RootMetadata) getUserDevicePublicKeys() (
   887  	writers, readers kbfsmd.UserDevicePublicKeys, err error) {
   888  	return md.bareMd.GetUserDevicePublicKeys(md.extra)
   889  }
   890  
   891  // GetTLFWriterKeyBundleID returns the ID of the externally-stored
   892  // writer key bundle, or the zero value if this object stores it
   893  // internally.
   894  func (md *RootMetadata) GetTLFWriterKeyBundleID() kbfsmd.TLFWriterKeyBundleID {
   895  	return md.bareMd.GetTLFWriterKeyBundleID()
   896  }
   897  
   898  // GetTLFReaderKeyBundleID returns the ID of the externally-stored
   899  // reader key bundle, or the zero value if this object stores it
   900  // internally.
   901  func (md *RootMetadata) GetTLFReaderKeyBundleID() kbfsmd.TLFReaderKeyBundleID {
   902  	return md.bareMd.GetTLFReaderKeyBundleID()
   903  }
   904  
   905  // StoresHistoricTLFCryptKeys implements the KeyMetadata interface for RootMetadata.
   906  func (md *RootMetadata) StoresHistoricTLFCryptKeys() bool {
   907  	return md.bareMd.StoresHistoricTLFCryptKeys()
   908  }
   909  
   910  // GetHistoricTLFCryptKey implements the KeyMetadata interface for RootMetadata.
   911  func (md *RootMetadata) GetHistoricTLFCryptKey(
   912  	codec kbfscodec.Codec, keyGen kbfsmd.KeyGen,
   913  	currentKey kbfscrypto.TLFCryptKey) (kbfscrypto.TLFCryptKey, error) {
   914  	return md.bareMd.GetHistoricTLFCryptKey(
   915  		codec, keyGen, currentKey, md.extra)
   916  }
   917  
   918  // IsWriter checks that the given user is a valid writer of the TLF
   919  // right now.  Implements the KeyMetadata interface for RootMetadata.
   920  func (md *RootMetadata) IsWriter(
   921  	ctx context.Context, checker kbfsmd.TeamMembershipChecker,
   922  	osg idutil.OfflineStatusGetter, uid keybase1.UID,
   923  	verifyingKey kbfscrypto.VerifyingKey) (bool, error) {
   924  	h := md.GetTlfHandle()
   925  	return IsWriterFromHandle(ctx, h, checker, osg, uid, verifyingKey)
   926  }
   927  
   928  // IsReader checks that the given user is a valid reader of the TLF
   929  // right now.
   930  func (md *RootMetadata) IsReader(
   931  	ctx context.Context, checker kbfsmd.TeamMembershipChecker,
   932  	osg idutil.OfflineStatusGetter, uid keybase1.UID) (bool, error) {
   933  	h := md.GetTlfHandle()
   934  	return isReaderFromHandle(ctx, h, checker, osg, uid)
   935  }
   936  
   937  // A ReadOnlyRootMetadata is a thin wrapper around a
   938  // *RootMetadata. Functions that take a ReadOnlyRootMetadata parameter
   939  // must not modify it, and therefore code that passes a
   940  // ReadOnlyRootMetadata to a function can assume that it is not
   941  // modified by that function. However, callers that convert a
   942  // *RootMetadata to a ReadOnlyRootMetadata may still modify the
   943  // underlying RootMetadata through the original pointer, so care must
   944  // be taken if a function stores a ReadOnlyRootMetadata object past
   945  // the end of the function, or when a function takes both a
   946  // *RootMetadata and a ReadOnlyRootMetadata (see
   947  // decryptMDPrivateData).
   948  type ReadOnlyRootMetadata struct {
   949  	*RootMetadata
   950  }
   951  
   952  // CheckValidSuccessor makes sure the given ReadOnlyRootMetadata is a
   953  // valid successor to the current one, and returns an error otherwise.
   954  func (md ReadOnlyRootMetadata) CheckValidSuccessor(
   955  	currID kbfsmd.ID, nextMd ReadOnlyRootMetadata) error {
   956  	return md.bareMd.CheckValidSuccessor(currID, nextMd.bareMd)
   957  }
   958  
   959  // ReadOnly makes a ReadOnlyRootMetadata from the current
   960  // *RootMetadata.
   961  func (md *RootMetadata) ReadOnly() ReadOnlyRootMetadata {
   962  	return ReadOnlyRootMetadata{md}
   963  }
   964  
   965  // ImmutableRootMetadata is a thin wrapper around a
   966  // ReadOnlyRootMetadata that takes ownership of it and does not ever
   967  // modify it again. Thus, its MdID can be calculated and
   968  // stored. Unlike ReadOnlyRootMetadata, ImmutableRootMetadata objects
   969  // can be assumed to never alias a (modifiable) *RootMetadata.
   970  type ImmutableRootMetadata struct {
   971  	ReadOnlyRootMetadata
   972  	mdID                   kbfsmd.ID
   973  	lastWriterVerifyingKey kbfscrypto.VerifyingKey
   974  	// localTimestamp represents the time at which the MD update was
   975  	// applied at the server, adjusted for the local clock.  So for
   976  	// example, it can be used to show how long ago a particular
   977  	// update happened (e.g., "5 hours ago").  Note that the update
   978  	// time supplied by the server is technically untrusted (i.e., not
   979  	// signed by a writer of the TLF, only provided by the server).
   980  	// If this ImmutableRootMetadata was generated locally and still
   981  	// persists in the journal or in the cache, localTimestamp comes
   982  	// directly from the local clock.
   983  	localTimestamp time.Time
   984  	// putToServer indicates whether this MD has been put successfully
   985  	// to the remote server (e.g., it isn't just local to the
   986  	// process's journal).
   987  	putToServer bool
   988  }
   989  
   990  // MakeImmutableRootMetadata makes a new ImmutableRootMetadata from
   991  // the given RMD and its corresponding MdID.
   992  func MakeImmutableRootMetadata(
   993  	rmd *RootMetadata, writerVerifyingKey kbfscrypto.VerifyingKey,
   994  	mdID kbfsmd.ID, localTimestamp time.Time,
   995  	putToServer bool) ImmutableRootMetadata {
   996  	if writerVerifyingKey == (kbfscrypto.VerifyingKey{}) {
   997  		panic("zero writerVerifyingKey passed to MakeImmutableRootMetadata")
   998  	}
   999  	if mdID == (kbfsmd.ID{}) {
  1000  		panic("zero mdID passed to MakeImmutableRootMetadata")
  1001  	}
  1002  	if localTimestamp.IsZero() {
  1003  		panic("zero localTimestamp passed to MakeImmutableRootMetadata")
  1004  	}
  1005  	if bareMDV2, ok := rmd.bareMd.(*kbfsmd.RootMetadataV2); ok {
  1006  		writerSig := bareMDV2.WriterMetadataSigInfo
  1007  		if writerSig.IsNil() {
  1008  			panic("MDV2 with nil writer signature")
  1009  		}
  1010  		if writerSig.VerifyingKey != writerVerifyingKey {
  1011  			panic(fmt.Sprintf("key mismatch: sig has %s, expected %s",
  1012  				writerSig.VerifyingKey, writerVerifyingKey))
  1013  		}
  1014  	}
  1015  	return ImmutableRootMetadata{
  1016  		rmd.ReadOnly(), mdID, writerVerifyingKey, localTimestamp, putToServer}
  1017  }
  1018  
  1019  // MdID returns the pre-computed MdID of the contained RootMetadata
  1020  // object.
  1021  func (irmd ImmutableRootMetadata) MdID() kbfsmd.ID {
  1022  	return irmd.mdID
  1023  }
  1024  
  1025  // LocalTimestamp returns the timestamp associated with this
  1026  // RootMetadata object.
  1027  func (irmd ImmutableRootMetadata) LocalTimestamp() time.Time {
  1028  	return irmd.localTimestamp
  1029  }
  1030  
  1031  // LastModifyingWriterVerifyingKey returns the VerifyingKey used by the last
  1032  // writer of this MD.
  1033  func (irmd ImmutableRootMetadata) LastModifyingWriterVerifyingKey() kbfscrypto.VerifyingKey {
  1034  	return irmd.lastWriterVerifyingKey
  1035  }
  1036  
  1037  // RootMetadataSigned is a wrapper around kbfsmd.RootMetadataSigned
  1038  // that adds an untrusted server timestamp.
  1039  type RootMetadataSigned struct {
  1040  	kbfsmd.RootMetadataSigned
  1041  	// When does the server say this MD update was received?  (This is
  1042  	// not necessarily trustworthy, just for informational purposes.)
  1043  	untrustedServerTimestamp time.Time
  1044  }
  1045  
  1046  // makeRootMetadataSigned makes a RootMetadataSigned object from the
  1047  // given info. If md stores the writer signature info internally, it
  1048  // must match the given one.
  1049  func makeRootMetadataSigned(rmds *kbfsmd.RootMetadataSigned,
  1050  	untrustedServerTimestamp time.Time) *RootMetadataSigned {
  1051  	return &RootMetadataSigned{
  1052  		RootMetadataSigned:       *rmds,
  1053  		untrustedServerTimestamp: untrustedServerTimestamp,
  1054  	}
  1055  }
  1056  
  1057  // SignBareRootMetadata signs the given BareRootMetadata and returns a
  1058  // *RootMetadataSigned object. rootMetadataSigner and
  1059  // writerMetadataSigner should be the same, except in tests.
  1060  func SignBareRootMetadata(
  1061  	ctx context.Context, codec kbfscodec.Codec,
  1062  	rootMetadataSigner, writerMetadataSigner kbfscrypto.Signer,
  1063  	md kbfsmd.RootMetadata, untrustedServerTimestamp time.Time) (
  1064  	*RootMetadataSigned, error) {
  1065  	rmds, err := kbfsmd.SignRootMetadata(ctx, codec, rootMetadataSigner, writerMetadataSigner, md)
  1066  	if err != nil {
  1067  		return nil, err
  1068  	}
  1069  	return makeRootMetadataSigned(rmds, untrustedServerTimestamp), nil
  1070  }
  1071  
  1072  // MakeFinalCopy returns a complete copy of this RootMetadataSigned
  1073  // with the revision incremented and the final bit set.
  1074  func (rmds *RootMetadataSigned) MakeFinalCopy(
  1075  	codec kbfscodec.Codec, now time.Time,
  1076  	finalizedInfo *tlf.HandleExtension) (*RootMetadataSigned, error) {
  1077  	rmdsCopy, err := rmds.RootMetadataSigned.MakeFinalCopy(codec, finalizedInfo)
  1078  	if err != nil {
  1079  		return nil, err
  1080  	}
  1081  	return makeRootMetadataSigned(rmdsCopy, now), nil
  1082  }
  1083  
  1084  // DecodeRootMetadataSigned deserializes a metadata block into the
  1085  // specified versioned structure.
  1086  func DecodeRootMetadataSigned(
  1087  	codec kbfscodec.Codec, tlf tlf.ID, ver, max kbfsmd.MetadataVer, buf []byte,
  1088  	untrustedServerTimestamp time.Time) (
  1089  	*RootMetadataSigned, error) {
  1090  	rmds, err := kbfsmd.DecodeRootMetadataSigned(codec, tlf, ver, max, buf)
  1091  	if err != nil {
  1092  		return nil, err
  1093  	}
  1094  	return makeRootMetadataSigned(rmds, untrustedServerTimestamp), nil
  1095  }