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
5package libkbfs
6
7import (
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.
25type KeyManagerStandard struct {
26	config   Config
27	log      logger.Logger
28	deferLog logger.Logger
29}
30
31// NewKeyManagerStandard returns a new KeyManagerStandard
32func 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.
39func (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.
47func (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.
56func (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.
64func (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.
73func (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
87func (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
97type getTLFCryptKeyFlags byte
98
99const (
100	getTLFCryptKeyAnyDevice getTLFCryptKeyFlags = 1 << iota
101	getTLFCryptKeyDoCache
102	getTLFCryptKeyPromptPaper
103)
104
105func (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
228func (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
349func (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
364func (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
393func (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
419func (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
445func (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.
474func (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.
502func (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}
901