github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/libkbfs/key_manager.go (about)

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