1// Copyright 2015 Keybase, Inc. All rights reserved. Use of
2// this source code is governed by the included BSD license.
3
4// A KeyFamily is a group of sibling keys that have equal power for a user.
5// A family can consist of 1 PGP keys, and arbitrarily many NaCl Sibkeys.
6// There also can be some subkeys dangling off for ECDH.
7package libkb
8
9import (
10	"errors"
11	"fmt"
12	"runtime/debug"
13	"sort"
14	"time"
15
16	"github.com/keybase/client/go/kbcrypto"
17	keybase1 "github.com/keybase/client/go/protocol/keybase1"
18	jsonw "github.com/keybase/go-jsonw"
19)
20
21// We have two notions of time we can use -- standard UTC which might
22// be screwy (skewy) based upon local clock problems; or MerkleRoot seqno,
23// which is totally ordered and all clients and server ought to agree on it.
24// The issue is that we're not uniformly signing Merkle roots into signatures,
25// especially those generated on the Web site.
26type KeybaseTime struct {
27	Unix  int64          // UTC wallclock time
28	Chain keybase1.Seqno // Merkle root chain time
29}
30
31// Struct for the DelegationsList
32type Delegation struct {
33	KID   keybase1.KID
34	SigID keybase1.SigID
35}
36
37type ComputedKeyInfosVersion int
38
39const (
40	ComputedKeyInfosV1             ComputedKeyInfosVersion = ComputedKeyInfosVersion(1)
41	ComputedKeyInfosV2             ComputedKeyInfosVersion = ComputedKeyInfosVersion(2)
42	ComputedKeyInfosV3             ComputedKeyInfosVersion = ComputedKeyInfosVersion(3)
43	ComputedKeyInfosV4             ComputedKeyInfosVersion = ComputedKeyInfosVersion(4)
44	ComputedKeyInfosVersionCurrent                         = ComputedKeyInfosV4
45)
46
47// refers to exactly one ServerKeyInfo.
48type ComputedKeyInfo struct {
49	Contextified
50
51	// Repeat the KID inside, for lookups if we get here via the
52	// `Sigs` map in ComputedKeyInfos
53	KID keybase1.KID
54
55	Status KeyStatus
56	Eldest bool
57	Sibkey bool
58
59	// These have to be ints so they can be written to disk and read
60	// back in.
61	CTime int64 // In Seconds since the Epoch
62	ETime int64 // In Seconds since the Epoch or 0 if none
63
64	// For subkeys, the KID of our parent (if valid)
65	Parent keybase1.KID
66
67	// For sibkeys, the KID of last-added subkey (if valid)
68	Subkey keybase1.KID
69
70	// Map of SigID -> KID
71	Delegations map[keybase1.SigIDMapKey]keybase1.KID
72
73	// List of the same delegations as above, in a way that preserves ordering.
74	// NOTE: This is not populated in older cached CKI's.
75	DelegationsList []Delegation
76
77	// Merkle Timestamps and Friends for delegation. Suboptimal grouping of concerns
78	// due to backwards compatibility and sensitivity to preexisting ondisk representations.
79	DelegatedAt                 *KeybaseTime              // The Seqno/Ctime signed into the link, so jus before the actual delegation!
80	DelegatedAtHashMeta         keybase1.HashMeta         // The HashMeta at the time of the delegation
81	FirstAppearedUnverified     keybase1.Seqno            // What the server claims was the first merkle appearance of this seqno
82	DelegatedAtSigChainLocation keybase1.SigChainLocation // Where the delegation was in our sigchain
83
84	// Merkle Timestamps and Friends for revocation.
85	RevokedAt                     *KeybaseTime // The Seqno/Ctime signed into the signature
86	RevokedBy                     keybase1.KID
87	RevokedAtHashMeta             keybase1.HashMeta          // The hash_meta signed in at the time of the revocation
88	RevokeFirstAppearedUnverified keybase1.Seqno             // What the server claims was the first merkle appearance of this revoke
89	RevokedAtSigChainLocation     *keybase1.SigChainLocation // Where the revocation was in our sigchain
90
91	// For PGP keys, the active version of the key. If unspecified, use the
92	// legacy behavior of combining every instance of this key that we got from
93	// the server minus revocations.
94	ActivePGPHash string
95}
96
97func (cki ComputedKeyInfo) GetCTime() time.Time {
98	return time.Unix(cki.CTime, 0)
99}
100
101func (cki ComputedKeyInfo) GetETime() time.Time {
102	return UnixToTimeMappingZero(cki.ETime)
103}
104
105// When we play a sigchain forward, it yields ComputedKeyInfos (CKIs). We're going to
106// store CKIs separately from the keys, since the server can clobber the
107// former.  We should rewrite CKIs every time we (re)check a user's SigChain
108type ComputedKeyInfos struct {
109	Contextified
110
111	// Now set to 1. Everything before that is thrown away on sigchain load.
112	Version ComputedKeyInfosVersion
113
114	dirty bool // whether it needs to be written to disk or not
115
116	// Map of KID to a computed info
117	Infos map[keybase1.KID]*ComputedKeyInfo
118
119	// Map of a SigID (in binary) to the ComputedKeyInfo describing when the key was
120	// delegated.
121	Sigs map[keybase1.SigIDMapKey]*ComputedKeyInfo
122
123	// Map of DeviceID to the most current device object
124	Devices map[keybase1.DeviceID]*Device
125
126	// Map of KID -> DeviceID
127	KIDToDeviceID map[keybase1.KID]keybase1.DeviceID
128
129	// For each generation, the public KIDs that correspond to the
130	// per-user-key for a given generation.
131	// Starts at gen=1.
132	PerUserKeys map[keybase1.PerUserKeyGeneration]keybase1.PerUserKey
133}
134
135// As returned by user/lookup.json
136type RawKeyFamily struct {
137	AllBundles []string `json:"all_bundles"`
138}
139
140// PGPKeySet represents a collection of versions of a PGP key. It includes a
141// merged version of the key without revocations, and each individual version
142// of the key with revocations intact.
143type PGPKeySet struct {
144	Contextified
145	PermissivelyMergedKey *PGPKeyBundle
146	KeysByHash            map[string]*PGPKeyBundle
147}
148
149func (s *PGPKeySet) addKey(key *PGPKeyBundle) error {
150	fullHash, err := key.FullHash()
151	if err != nil {
152		return err
153	}
154
155	// Only the KID (and sometimes the fingerprint) of PGP keys has
156	// historically been signed into the sigchain. When validating a sigchain
157	// and multiple versions of the PGP key are available (which may be
158	// different in terms of subkeys, UIDs, and revocations) we chose to merge
159	// every version and ignore revocations. This stops anyone from breaking
160	// their sigchain by uploading a revoked version of their PGP key, but also
161	// creates a vulnerability when Alice's key is compromised and she revokes
162	// it PGP-style without revoking it sigchain-style: Keybase clients will
163	// continue to accept the key, Mallory can now make sigchain links as
164	// Alice.
165	//
166	// As a long term solution, we decided that PGP keys' full hashes over time
167	// should be tracked in the sigchain so that the client can know which
168	// version to use to validate each link. This is detailed in issue #544.
169	//
170	// PGPKeySet keeps both the individual versions of the key, indexed by
171	// hash, and the permissively-merged version to support both the old
172	// behavior (for sigchains or sections of sigchains with no specific PGP
173	// key hash) and the new behavior.
174
175	s.G().Log.Debug("adding PGP kid %s with full hash %s", key.GetKID().String(), fullHash)
176	s.KeysByHash[fullHash] = key
177
178	strippedKey := key.StripRevocations()
179	if s.PermissivelyMergedKey == nil {
180		s.PermissivelyMergedKey = strippedKey
181	} else {
182		s.PermissivelyMergedKey.MergeKey(strippedKey)
183	}
184	return nil
185}
186
187// Once the client downloads a RawKeyFamily, it converts it into a KeyFamily,
188// which has some additional information about Fingerprints and PGP keys
189type KeyFamily struct {
190	// These fields are computed on the client side, so they can be trusted.
191	pgp2kid map[PGPFingerprint]keybase1.KID
192	kid2pgp map[keybase1.KID]PGPFingerprint
193
194	AllKIDs map[keybase1.KID]bool
195
196	// PGP keys have a permissively merged version and individual versions by
197	// hash. See the comment in PGPKeySet.addKey, above, for details.
198	PGPKeySets map[keybase1.KID]*PGPKeySet
199	SingleKeys map[keybase1.KID]GenericKey // Currently just NaCl keys
200
201	BundlesForTesting []string
202
203	Contextified
204}
205
206// ComputedKeyFamily is a joining of two sets of data; the KeyFamily is
207// what the server returned and is not to be trusted; the ComputedKeyInfos
208// is what we compute as a result of playing the user's sigchain forward.
209type ComputedKeyFamily struct {
210	Contextified
211	kf  *KeyFamily
212	cki *ComputedKeyInfos
213}
214
215// Insert inserts the given ComputedKeyInfo object 1 or 2 times,
216// depending on if a KID or PGPFingerprint or both are available.
217func (cki *ComputedKeyInfos) Insert(i *ComputedKeyInfo) {
218	cki.Infos[i.KID] = i
219	cki.dirty = true
220}
221
222// PaperDevices returns a list of all the paperkey devices.
223func (cki *ComputedKeyInfos) PaperDevices() []*Device {
224	var d []*Device
225	for _, v := range cki.Devices {
226		if v.Status == nil {
227			continue
228		}
229		if *v.Status != DeviceStatusActive {
230			continue
231		}
232		if v.Type != keybase1.DeviceTypeV2_PAPER {
233			continue
234		}
235		d = append(d, v)
236	}
237	return d
238}
239
240// TODO: Figure out whether this needs to be a deep copy. See
241// https://github.com/keybase/client/issues/414 .
242func (cki ComputedKeyInfos) ShallowCopy() *ComputedKeyInfos {
243	ret := &ComputedKeyInfos{
244		Contextified:  NewContextified(cki.G()),
245		dirty:         cki.dirty,
246		Version:       cki.Version,
247		Infos:         make(map[keybase1.KID]*ComputedKeyInfo, len(cki.Infos)),
248		Sigs:          make(map[keybase1.SigIDMapKey]*ComputedKeyInfo, len(cki.Sigs)),
249		Devices:       make(map[keybase1.DeviceID]*Device, len(cki.Devices)),
250		KIDToDeviceID: make(map[keybase1.KID]keybase1.DeviceID, len(cki.KIDToDeviceID)),
251		PerUserKeys:   make(map[keybase1.PerUserKeyGeneration]keybase1.PerUserKey),
252	}
253	for k, v := range cki.Infos {
254		ret.Infos[k] = v
255	}
256
257	for k, v := range cki.Sigs {
258		ret.Sigs[k] = v
259	}
260
261	for k, v := range cki.Devices {
262		ret.Devices[k] = v
263	}
264
265	for k, v := range cki.KIDToDeviceID {
266		ret.KIDToDeviceID[k] = v
267	}
268
269	for k, v := range cki.PerUserKeys {
270		ret.PerUserKeys[k] = v
271	}
272
273	return ret
274}
275
276func (kf KeyFamily) ShallowCopy() *KeyFamily {
277	ret := &KeyFamily{
278		Contextified: NewContextified(kf.G()),
279		pgp2kid:      make(map[PGPFingerprint]keybase1.KID),
280		kid2pgp:      make(map[keybase1.KID]PGPFingerprint),
281		AllKIDs:      make(map[keybase1.KID]bool),
282		PGPKeySets:   make(map[keybase1.KID]*PGPKeySet),
283		SingleKeys:   make(map[keybase1.KID]GenericKey),
284	}
285
286	for k, v := range kf.pgp2kid {
287		ret.pgp2kid[k] = v
288	}
289
290	for k, v := range kf.kid2pgp {
291		ret.kid2pgp[k] = v
292	}
293
294	for k, v := range kf.AllKIDs {
295		ret.AllKIDs[k] = v
296	}
297
298	for k, v := range kf.PGPKeySets {
299		ret.PGPKeySets[k] = v
300	}
301
302	for k, v := range kf.SingleKeys {
303		ret.SingleKeys[k] = v
304	}
305
306	return ret
307}
308
309func (ckf ComputedKeyFamily) ShallowCopy() *ComputedKeyFamily {
310	ret := &ComputedKeyFamily{
311		Contextified: NewContextified(ckf.G()),
312	}
313	if ckf.kf != nil {
314		ret.kf = ckf.kf.ShallowCopy()
315	}
316	if ckf.cki != nil {
317		ret.cki = ckf.cki.ShallowCopy()
318	}
319	return ret
320}
321
322func NewComputedKeyInfos(g *GlobalContext) *ComputedKeyInfos {
323	return &ComputedKeyInfos{
324		Contextified:  NewContextified(g),
325		Version:       ComputedKeyInfosVersionCurrent,
326		Infos:         make(map[keybase1.KID]*ComputedKeyInfo),
327		Sigs:          make(map[keybase1.SigIDMapKey]*ComputedKeyInfo),
328		Devices:       make(map[keybase1.DeviceID]*Device),
329		KIDToDeviceID: make(map[keybase1.KID]keybase1.DeviceID),
330		PerUserKeys:   make(map[keybase1.PerUserKeyGeneration]keybase1.PerUserKey),
331	}
332}
333
334func NewComputedKeyInfo(kid keybase1.KID, eldest, sibkey bool, status KeyStatus, ctime, etime int64, activePGPHash string) ComputedKeyInfo {
335	return ComputedKeyInfo{
336		KID:           kid,
337		Eldest:        eldest,
338		Sibkey:        sibkey,
339		Status:        status,
340		CTime:         ctime,
341		ETime:         etime,
342		Delegations:   make(map[keybase1.SigIDMapKey]keybase1.KID),
343		ActivePGPHash: activePGPHash,
344	}
345}
346
347func (cki ComputedKeyInfos) InsertLocalEldestKey(kid keybase1.KID) {
348	// CTime and ETime are both initialized to zero, meaning that (until we get
349	// updates from the server) this key never expires.
350	eldestCki := NewComputedKeyInfo(kid, true, true, KeyUncancelled, 0, 0, "" /* activePGPHash */)
351	cki.Insert(&eldestCki)
352}
353
354// For use when there are no chain links at all, so all we can do is trust the
355// eldest key that the server reported.
356func (cki ComputedKeyInfos) InsertServerEldestKey(eldestKey GenericKey, un NormalizedUsername) error {
357	kbid := KeybaseIdentity(cki.G(), un)
358	if pgp, ok := eldestKey.(*PGPKeyBundle); ok {
359
360		// In the future, we might choose to ignore this etime, as we do in
361		// InsertEldestLink below. When we do make that change, be certain
362		// to update the comment in PGPKeyBundle#CheckIdentity to reflect it.
363		// For now, we continue to honor the foo_user@keybase.io etime in the case
364		// there's no sigchain link over the key to specify a different etime.
365		match, ctime, etime := pgp.CheckIdentity(kbid)
366		etime = cki.G().HonorPGPExpireTime(etime)
367		if match {
368			kid := eldestKey.GetKID()
369			eldestCki := NewComputedKeyInfo(kid, true, true, KeyUncancelled, ctime, etime, "" /* activePGPHash */)
370			cki.Insert(&eldestCki)
371			return nil
372		}
373		return KeyFamilyError{"InsertServerEldestKey found a non-matching eldest key."}
374	}
375	return KeyFamilyError{"InsertServerEldestKey found a non-PGP key."}
376}
377
378func (ckf ComputedKeyFamily) InsertEldestLink(tcl TypedChainLink, username NormalizedUsername) (err error) {
379	ckf.G().Log.Debug("ComputedKeyFamily#InsertEldestLink %s", tcl.ToDebugString())
380
381	kid := tcl.GetKID()
382	tm := TclToKeybaseTime(tcl)
383
384	_, err = ckf.FindKeyWithKIDUnsafe(kid)
385	if err != nil {
386		return
387	}
388
389	mhm, err := tcl.GetMerkleHashMeta()
390	if err != nil {
391		return err
392	}
393
394	// We don't need to check the signature on the first link, because
395	// verifySubchain will take care of that.
396	ctime := tcl.GetCTime().Unix()
397	etime := ckf.G().HonorSigchainExpireTime(tcl.GetETime().Unix())
398
399	eldestCki := NewComputedKeyInfo(kid, true, true, KeyUncancelled, ctime, etime, tcl.GetPGPFullHash())
400	eldestCki.DelegatedAt = tm
401	eldestCki.DelegatedAtHashMeta = mhm
402	eldestCki.DelegatedAtSigChainLocation = tcl.ToSigChainLocation()
403
404	// Tricky legacy detail: Note that we have not inserted the eldest sig into
405	// the Delegations map here. verifySubchain() might go on to do that after
406	// we return if the link is of a delegating type (type:eldest or
407	// type:sibkey), but that's not always the case. Omitting the delegation
408	// from that map means that revoking the signature does *not* revoke the
409	// key it (implicitly) delegated. For example, Max's eldest link is a
410	// twitter proof, which is revoked. That *must not* count as a revocation
411	// of his eldest key. We have a copy of Max's sigchain as one of our test
412	// vectors, to cover this behavior. See also the note in RevokeSig.
413
414	ckf.cki.Insert(&eldestCki)
415	return nil
416}
417
418// ParseKeyFamily takes as input a dictionary from a JSON file and returns
419// a parsed version for manipulation in the program.
420func ParseKeyFamily(g *GlobalContext, jw *jsonw.Wrapper) (ret *KeyFamily, err error) {
421	defer g.Trace("ParseKeyFamily", &err)()
422
423	if jw == nil || jw.IsNil() {
424		err = KeyFamilyError{"nil record from server"}
425		return
426	}
427
428	kf := KeyFamily{
429		Contextified: NewContextified(g),
430		pgp2kid:      make(map[PGPFingerprint]keybase1.KID),
431		kid2pgp:      make(map[keybase1.KID]PGPFingerprint),
432	}
433
434	// Fill in AllKeys. Somewhat wasteful but probably faster than
435	// using Jsonw wrappers, and less error-prone.
436	var rkf RawKeyFamily
437	if err = jw.UnmarshalAgain(&rkf); err != nil {
438		return
439	}
440	kf.BundlesForTesting = rkf.AllBundles
441
442	// Parse the keys, and collect the PGP keys to map their fingerprints.
443	kf.AllKIDs = make(map[keybase1.KID]bool)
444	kf.PGPKeySets = make(map[keybase1.KID]*PGPKeySet)
445	kf.SingleKeys = make(map[keybase1.KID]GenericKey)
446	for i, bundle := range rkf.AllBundles {
447		newKey, w, err := ParseGenericKey(bundle)
448
449		// Some users have some historical bad keys, so no reason to crap
450		// out if we can't parse them, especially if there are others than
451		// can do just as well.
452		if err != nil {
453			g.Log.Notice("Failed to parse public key at position %d", i)
454			g.Log.Debug("Key parsing error: %s", err)
455			g.Log.Debug("Full key dump follows")
456			g.Log.Debug(bundle)
457			continue
458		}
459		w.Warn(g)
460
461		kid := newKey.GetKID()
462
463		if pgp, isPGP := newKey.(*PGPKeyBundle); isPGP {
464			ks, ok := kf.PGPKeySets[kid]
465			if !ok {
466				ks = &PGPKeySet{NewContextified(g), nil, make(map[string]*PGPKeyBundle)}
467				kf.PGPKeySets[kid] = ks
468
469				fp := pgp.GetFingerprint()
470				kf.pgp2kid[fp] = kid
471				kf.kid2pgp[kid] = fp
472			}
473			err = ks.addKey(pgp)
474			if err != nil {
475				return nil, err
476			}
477		} else {
478			kf.SingleKeys[kid] = newKey
479		}
480		kf.AllKIDs[kid] = true
481	}
482
483	ret = &kf
484	return
485}
486
487// FindKeyWithKIDUnsafe returns a key given a KID. It doesn't check if the key
488// is expired or revoked, so most callers should use the FindActive* methods.
489func (ckf ComputedKeyFamily) FindKeyWithKIDUnsafe(kid keybase1.KID) (GenericKey, error) {
490	if key, ok := ckf.kf.SingleKeys[kid]; ok {
491		return key, nil
492	}
493	if ks, ok := ckf.kf.PGPKeySets[kid]; ok {
494		if ckf.cki != nil {
495			if cki, found := ckf.cki.Infos[kid]; found && cki.ActivePGPHash != "" {
496				if key, ok := ks.KeysByHash[cki.ActivePGPHash]; ok {
497					return key, nil
498				}
499				return nil, NoKeyError{fmt.Sprintf("Sigchain specified that KID %s is a PGP key with hash %s but no version of the key with that hash was found", kid, cki.ActivePGPHash)}
500			}
501		}
502		return ks.PermissivelyMergedKey, nil
503	}
504	return nil, KeyFamilyError{fmt.Sprintf("No key found for %s", kid)}
505}
506
507func (ckf ComputedKeyFamily) getCkiUnchecked(kid keybase1.KID) (ret *ComputedKeyInfo) {
508	return ckf.cki.Infos[kid]
509}
510
511func (ckf ComputedKeyFamily) getCkiIfActiveAtTime(kid keybase1.KID, t time.Time) (ret *ComputedKeyInfo, err error) {
512	unixTime := t.Unix()
513	if ki := ckf.cki.Infos[kid]; ki == nil {
514		err = NoKeyError{fmt.Sprintf("The key '%s' wasn't found", kid)}
515	} else if ki.Status != KeyUncancelled {
516		err = KeyRevokedError{fmt.Sprintf("The key '%s' is no longer active", kid)}
517	} else if ki.ETime > 0 && unixTime > ki.ETime {
518		formatStr := "Mon Jan 2 15:04:05 -0700 MST 2006"
519		ckf.G().Log.Warning("Checking status of key %s\n    with respect to time [%s],\n    found it had expired at [%s].",
520			kid, t.Format(formatStr), time.Unix(ki.ETime, 0).Format(formatStr))
521		err = KeyExpiredError{fmt.Sprintf("The key '%s' expired at %s", kid, time.Unix(ki.ETime, 0))}
522	} else {
523		ret = ki
524	}
525	return
526}
527
528func (ckf ComputedKeyFamily) getCkiIfActiveNow(kid keybase1.KID) (ret *ComputedKeyInfo, err error) {
529	return ckf.getCkiIfActiveAtTime(kid, time.Now())
530}
531
532// FindActiveSibkey takes a given KID and finds the corresponding active sibkey
533// in the current key family. If it cannot find the key, or if the key is no
534// longer active (either by revocation, or by expiring), it will return an
535// error saying why. Otherwise, it will return the key.  In this case either
536// key is non-nil, or err is non-nil.
537func (ckf ComputedKeyFamily) FindActiveSibkey(kid keybase1.KID) (key GenericKey, cki ComputedKeyInfo, err error) {
538	return ckf.FindActiveSibkeyAtTime(kid, time.Now())
539}
540
541// As FindActiveSibkey, but for a specific time. Note that going back in time
542// only affects expiration, not revocation. Thus this function is mainly useful
543// for validating the sigchain, when each delegation and revocation is getting
544// replayed in order.
545func (ckf ComputedKeyFamily) FindActiveSibkeyAtTime(kid keybase1.KID, t time.Time) (key GenericKey, cki ComputedKeyInfo, err error) {
546	liveCki, err := ckf.getCkiIfActiveAtTime(kid, t)
547	if liveCki == nil || err != nil {
548		// err gets returned.
549	} else if !liveCki.Sibkey {
550		err = kbcrypto.BadKeyError{Msg: fmt.Sprintf("The key '%s' wasn't delegated as a sibkey", kid)}
551	} else {
552		key, err = ckf.FindKeyWithKIDUnsafe(kid)
553		cki = *liveCki
554	}
555	return
556}
557
558// FindActiveEncryptionSubkey takes a given KID and finds the corresponding
559// active encryption subkey in the current key family.  If for any reason it
560// cannot find the key, it will return an error saying why.  Otherwise, it will
561// return the key.  In this case either key is non-nil, or err is non-nil.
562func (ckf ComputedKeyFamily) FindActiveEncryptionSubkey(kid keybase1.KID) (ret GenericKey, cki ComputedKeyInfo, err error) {
563	ckip, err := ckf.getCkiIfActiveNow(kid)
564	if err != nil {
565		return nil, cki, err
566	}
567	if ckip.Sibkey {
568		return nil, cki, kbcrypto.BadKeyError{Msg: fmt.Sprintf("The key '%s' was delegated as a sibkey", kid.String())}
569	}
570	key, err := ckf.FindKeyWithKIDUnsafe(kid)
571	if err != nil {
572		return nil, cki, err
573	}
574	if !CanEncrypt(key) {
575		return nil, cki, kbcrypto.BadKeyError{Msg: fmt.Sprintf("The key '%s' cannot encrypt", kid.String())}
576	}
577	return key, *ckip, nil
578}
579
580func (ckf ComputedKeyFamily) FindKIDFromFingerprint(fp PGPFingerprint) (kid keybase1.KID, err error) {
581	kid, ok := ckf.kf.pgp2kid[fp]
582	if !ok {
583		return kid, NoKeyError{fmt.Sprintf("No key found in key family for %q", fp)}
584	}
585	return kid, nil
586}
587
588// TclToKeybaseTime turns a TypedChainLink into a KeybaseTime tuple, looking
589// inside the chainlink for the Unix wallclock and the global MerkleChain seqno.
590func TclToKeybaseTime(tcl TypedChainLink) *KeybaseTime {
591	return &KeybaseTime{
592		Unix:  tcl.GetCTime().Unix(),
593		Chain: tcl.GetMerkleSeqno(),
594	}
595}
596
597// NowAsKeybaseTime makes a representation of now.  IF we don't know the MerkleTree
598// chain seqno, just use 0
599func NowAsKeybaseTime(seqno keybase1.Seqno) *KeybaseTime {
600	return &KeybaseTime{
601		Unix:  time.Now().Unix(),
602		Chain: seqno,
603	}
604}
605
606// Delegate performs a delegation to the key described in the given TypedChainLink.
607// This maybe be a sub- or sibkey delegation.
608func (ckf *ComputedKeyFamily) Delegate(tcl TypedChainLink) (err error) {
609
610	kid := tcl.GetDelegatedKid()
611	sigid := tcl.GetSigID()
612	tm := TclToKeybaseTime(tcl)
613
614	if kid.IsNil() {
615		debug.PrintStack()
616		return KeyFamilyError{fmt.Sprintf("Delegated KID is nil %T", tcl)}
617	}
618
619	if _, err := ckf.FindKeyWithKIDUnsafe(kid); err != nil {
620		return KeyFamilyError{fmt.Sprintf("Delegated KID %s is not in the key family", kid.String())}
621	}
622
623	mhm, err := tcl.GetMerkleHashMeta()
624	if err != nil {
625		return err
626	}
627
628	err = ckf.cki.Delegate(kid, tm, sigid, tcl.GetKID(), tcl.GetParentKid(),
629		tcl.GetPGPFullHash(), (tcl.GetRole() == DLGSibkey), tcl.GetCTime(), tcl.GetETime(),
630		mhm, tcl.GetFirstAppearedMerkleSeqnoUnverified(), tcl.ToSigChainLocation())
631	return
632}
633
634func (ckf *ComputedKeyFamily) DelegatePerUserKey(perUserKey keybase1.PerUserKey) (err error) {
635	return ckf.cki.DelegatePerUserKey(perUserKey)
636}
637
638// Delegate marks the given ComputedKeyInfos object that the given kid is now
639// delegated, as of time tm, in sigid, as signed by signingKid, etc.
640// fau = "FirstAppearedUnverified", a hint from the server that we're going to persist.
641// dascl = "DelegatedAtSigChainLocation"
642func (cki *ComputedKeyInfos) Delegate(kid keybase1.KID, tm *KeybaseTime, sigid keybase1.SigID, signingKid, parentKID keybase1.KID,
643	pgpHash string, isSibkey bool, ctime, etime time.Time,
644	merkleHashMeta keybase1.HashMeta, fau keybase1.Seqno,
645	dascl keybase1.SigChainLocation) (err error) {
646
647	cki.G().Log.Debug("ComputeKeyInfos#Delegate To %s with %s at sig %s", kid.String(), signingKid, sigid.ToDisplayString(true))
648	info, found := cki.Infos[kid]
649	etimeUnix := cki.G().HonorSigchainExpireTime(etime.Unix())
650	if !found {
651		newInfo := NewComputedKeyInfo(kid, false, isSibkey, KeyUncancelled, ctime.Unix(), etimeUnix, pgpHash)
652		newInfo.DelegatedAt = tm
653		info = &newInfo
654		cki.Infos[kid] = info
655	} else {
656		info.Status = KeyUncancelled
657		info.CTime = ctime.Unix()
658		info.ETime = etimeUnix
659		info.ActivePGPHash = pgpHash
660	}
661	info.Delegations[sigid.ToMapKey()] = signingKid
662	info.DelegationsList = append(info.DelegationsList, Delegation{signingKid, sigid})
663	info.Sibkey = isSibkey
664	info.DelegatedAtHashMeta = merkleHashMeta.DeepCopy()
665	info.DelegatedAtSigChainLocation = dascl.DeepCopy()
666	info.FirstAppearedUnverified = fau
667
668	cki.Sigs[sigid.ToMapKey()] = info
669
670	// If it's a subkey, make a pointer from it to its parent,
671	// and also from its parent to it.
672	if parentKID.Exists() {
673		info.Parent = parentKID
674		if parent, found := cki.Infos[parentKID]; found {
675			parent.Subkey = kid
676		}
677	}
678	return
679}
680
681func (cki *ComputedKeyInfos) IsStaleVersion() bool {
682	return cki.Version < ComputedKeyInfosVersionCurrent
683}
684
685// DelegatePerUserKey inserts the new per-user key into the list of known per-user keys.
686func (cki *ComputedKeyInfos) DelegatePerUserKey(perUserKey keybase1.PerUserKey) (err error) {
687	if perUserKey.Gen <= 0 {
688		return fmt.Errorf("invalid per-user-key generation %v", perUserKey.Gen)
689	}
690	if perUserKey.Seqno == 0 {
691		return fmt.Errorf("invalid per-user-key seqno: %v", perUserKey.Seqno)
692	}
693	if perUserKey.SigKID.IsNil() {
694		return errors.New("nil per-user-key sig kid")
695	}
696	if perUserKey.EncKID.IsNil() {
697		return errors.New("nil per-user-key enc kid")
698	}
699	if perUserKey.SignedByKID.IsNil() {
700		return errors.New("nil per-user-key signed-by kid")
701	}
702	cki.PerUserKeys[keybase1.PerUserKeyGeneration(perUserKey.Gen)] = perUserKey
703	return nil
704}
705
706// Revoke examines a TypeChainLink and applies any revocations in the link
707// to the current ComputedKeyInfos.
708func (ckf *ComputedKeyFamily) Revoke(tcl TypedChainLink) (err error) {
709	err = ckf.revokeSigs(tcl.GetRevocations(), tcl)
710	if err == nil {
711		err = ckf.revokeKids(tcl.GetRevokeKids(), tcl)
712	}
713	return err
714}
715
716// SetPGPHash sets the authoritative version (by hash) of a PGP key
717func (ckf *ComputedKeyFamily) SetActivePGPHash(kid keybase1.KID, hash string) {
718	found := false
719	if ks, ok := ckf.kf.PGPKeySets[kid]; ok && ks != nil && ks.KeysByHash[hash] != nil {
720		found = true
721	}
722	if !found {
723		// We've noted this case in the wild (see CORE-4771). It occured
724		// because the server accepted a new Cv25519 key, but an old client
725		// failed to parse it in ParseKeyFamily above. So just warn here.
726		// We expect, though, that if you get this Warning there is trouble ahead,
727		// and FindKeyWithKIDUnsafe will return nil.
728		ckf.G().Log.Warning("Didn't have a PGP key for %s with hash %s", kid, hash)
729	}
730	if _, ok := ckf.cki.Infos[kid]; ok {
731		ckf.cki.Infos[kid].ActivePGPHash = hash
732	} else {
733		ckf.G().Log.Debug("| Skipped setting active hash, since key was never delegated")
734	}
735}
736
737// ClearActivePGPHash clears authoritative hash of PGP key, after a revoke.
738func (ckf *ComputedKeyFamily) ClearActivePGPHash(kid keybase1.KID) {
739	if _, ok := ckf.cki.Infos[kid]; ok {
740		ckf.cki.Infos[kid].ActivePGPHash = ""
741	} else {
742		ckf.G().Log.Debug("| Skipped clearing active hash, since key was never delegated")
743	}
744}
745
746// revokeSigs operates on the per-signature revocations in the given
747// TypedChainLink and applies them accordingly.
748func (ckf *ComputedKeyFamily) revokeSigs(sigs []keybase1.SigID, tcl TypedChainLink) error {
749	for _, s := range sigs {
750		if len(s) == 0 {
751			continue
752		}
753		if err := ckf.RevokeSig(s, tcl); err != nil {
754			return err
755		}
756	}
757	return nil
758}
759
760// revokeKids operates on the per-kid revocations in the given
761// TypedChainLink and applies them accordingly.
762func (ckf *ComputedKeyFamily) revokeKids(kids []keybase1.KID, tcl TypedChainLink) (err error) {
763	for _, k := range kids {
764		if k.Exists() {
765			if err = ckf.RevokeKid(k, tcl); err != nil {
766				return
767			}
768		}
769	}
770	return
771}
772
773func (ckf *ComputedKeyFamily) RevokeSig(sig keybase1.SigID, tcl TypedChainLink) (err error) {
774	if info, found := ckf.cki.Sigs[sig.ToMapKey()]; !found {
775		// silently no-op if the signature doesn't exist
776	} else if _, found := info.Delegations[sig.ToMapKey()]; found {
777		// Tricky legacy detail: For some eldest links that implicitly delegate
778		// keys, the info.Delegations map will not contain the delegation, and
779		// we will skip this branch. We rely on this behavior to avoid revoking
780		// keys that shouldn't be revoked. See the note in InsertEldestLink.
781
782		info.Status = KeyRevoked
783		info.RevokedAt = TclToKeybaseTime(tcl)
784		info.RevokedBy = tcl.GetKID()
785		tmp := tcl.ToSigChainLocation()
786		info.RevokedAtSigChainLocation = &tmp
787		mhm, err := tcl.GetMerkleHashMeta()
788		if err != nil {
789			return err
790		}
791		info.RevokedAtHashMeta = mhm
792		info.RevokeFirstAppearedUnverified = tcl.GetFirstAppearedMerkleSeqnoUnverified()
793		kid := info.KID
794
795		if KIDIsPGP(kid) {
796			ckf.ClearActivePGPHash(kid)
797		}
798	} else {
799		err = BadRevocationError{fmt.Sprintf("Can't find sigID %s in delegation list", sig)}
800	}
801	return
802}
803
804func (ckf *ComputedKeyFamily) RevokeKid(kid keybase1.KID, tcl TypedChainLink) (err error) {
805	if info, found := ckf.cki.Infos[kid]; found {
806		info.Status = KeyRevoked
807		info.RevokedAt = TclToKeybaseTime(tcl)
808		info.RevokedBy = tcl.GetKID()
809		tmp := tcl.ToSigChainLocation()
810		info.RevokedAtSigChainLocation = &tmp
811		mhm, err := tcl.GetMerkleHashMeta()
812		if err != nil {
813			return err
814		}
815		info.RevokedAtHashMeta = mhm
816		info.RevokeFirstAppearedUnverified = tcl.GetFirstAppearedMerkleSeqnoUnverified()
817
818		if KIDIsPGP(kid) {
819			ckf.ClearActivePGPHash(kid)
820		}
821	}
822	return
823}
824
825// FindKeybaseName looks at all PGP keys in this key family that are active
826// sibkeys to find a key with a signed identity of <name@keybase.io>. IF
827// found return true, and otherwise false.
828func (ckf ComputedKeyFamily) FindKeybaseName(s string) bool {
829	kem := KeybaseEmailAddress(s)
830	for kid := range ckf.kf.PGPKeySets {
831		if info, found := ckf.cki.Infos[kid]; !found {
832			continue
833		} else if info.Status != KeyUncancelled || !info.Sibkey {
834			continue
835		}
836		pgp := ckf.kf.PGPKeySets[kid].PermissivelyMergedKey
837		if pgp.FindEmail(kem) {
838			ckf.G().Log.Debug("| Found self-sig for %s in key ID: %s", s, kid)
839			return true
840		}
841	}
842	return false
843}
844
845// LocalDelegate performs a local key delegation, without the server's permissions.
846// We'll need to do this when a key is locally generated.
847func (kf *KeyFamily) LocalDelegate(key GenericKey) (err error) {
848	if pgp, ok := key.(*PGPKeyBundle); ok {
849		kid := pgp.GetKID()
850		kf.pgp2kid[pgp.GetFingerprint()] = kid
851	}
852	kf.SingleKeys[key.GetKID()] = key
853	return
854}
855
856// GetKeyRoleAtTime returns the KeyRole (sibkey/subkey/none), taking into
857// account whether the key has been cancelled at time t.
858func (ckf ComputedKeyFamily) GetKeyRoleAtTime(kid keybase1.KID, t time.Time) (ret KeyRole) {
859	if info, err := ckf.getCkiIfActiveAtTime(kid, t); err != nil {
860		ckf.G().Log.Debug("GetKeyRoleAtTime %s, %s => err %s", kid, t, err)
861		ret = DLGNone
862	} else if info.Sibkey {
863		ret = DLGSibkey
864	} else {
865		ret = DLGSubkey
866	}
867	return
868}
869
870// GetAllSibkeysUnchecked gets all sibkeys, dead or otherwise, that were at one point associated
871// with this key family.
872func (ckf ComputedKeyFamily) GetAllSibkeysUnchecked() (ret []GenericKey) {
873	return ckf.getAllKeysUnchecked(DLGSibkey)
874}
875
876// GetAllSubkeysUnchecked gets all sibkeys, dead or otherwise, that were at one point associated
877// with this key family.
878func (ckf ComputedKeyFamily) GetAllSubkeysUnchecked() (ret []GenericKey) {
879	return ckf.getAllKeysUnchecked(DLGSubkey)
880}
881
882func (ckf ComputedKeyFamily) getAllKeysUnchecked(role KeyRole) (ret []GenericKey) {
883	for kid := range ckf.kf.AllKIDs {
884		info := ckf.getCkiUnchecked(kid)
885		if info != nil && ((info.Sibkey && role == DLGSibkey) || (!info.Sibkey && role == DLGSubkey)) {
886			key, err := ckf.FindKeyWithKIDUnsafe(kid)
887			if err != nil {
888				ckf.G().Log.Warning("GetAllSibkeys: Error in getting KID %s: %s", kid, err)
889			}
890			ret = append(ret, key)
891		}
892	}
893	return ret
894}
895
896// GetKeyRole returns the KeyRole (sibkey/subkey/none), taking into account
897// whether the key has been cancelled.
898func (ckf ComputedKeyFamily) GetKeyRole(kid keybase1.KID) (ret KeyRole) {
899	return ckf.GetKeyRoleAtTime(kid, time.Now())
900}
901
902// GetAllActiveSibkeys gets all active Sibkeys from given ComputedKeyFamily.
903func (ckf ComputedKeyFamily) GetAllActiveKeysWithRoleAtTime(role KeyRole, t time.Time) (ret []GenericKey) {
904	for kid := range ckf.kf.AllKIDs {
905		if ckf.GetKeyRoleAtTime(kid, t) == role {
906			key, err := ckf.FindKeyWithKIDUnsafe(kid)
907			if err != nil {
908				ckf.G().Log.Warning("GetAllActiveKeysWithRoleAtTime: Error in getting KID %s: %s", kid, err)
909			}
910			if key == nil {
911				ckf.G().Log.Warning("GetAllActiveKeysWithRoleAtTime: Null key for KID %s", kid)
912			} else {
913				ret = append(ret, key)
914			}
915		}
916	}
917	return
918}
919
920// GetAllActiveSibkeys gets all active Sibkeys from given ComputedKeyFamily.
921func (ckf ComputedKeyFamily) GetAllActiveSibkeysAtTime(t time.Time) []GenericKey {
922	return ckf.GetAllActiveKeysWithRoleAtTime(DLGSibkey, t)
923}
924
925// GetAllActiveSibkeys gets all active Sibkeys from given ComputedKeyFamily.
926func (ckf ComputedKeyFamily) GetAllActiveSibkeys() []GenericKey {
927	return ckf.GetAllActiveSibkeysAtTime(time.Now())
928}
929
930func (ckf ComputedKeyFamily) GetAllActiveSubkeysAtTime(t time.Time) (ret []GenericKey) {
931	return ckf.GetAllActiveKeysWithRoleAtTime(DLGSubkey, t)
932}
933
934func (ckf ComputedKeyFamily) GetAllActiveSubkeys() []GenericKey {
935	return ckf.GetAllActiveSubkeysAtTime(time.Now())
936}
937
938func (ckf ComputedKeyFamily) GetAllActiveKeysForDevice(deviceID keybase1.DeviceID) ([]keybase1.KID, error) {
939	_, deviceExists := ckf.cki.Devices[deviceID]
940	if !deviceExists {
941		return nil, fmt.Errorf("Device %s does not exist.", deviceID)
942	}
943	var ret []keybase1.KID
944	// Find the sibkey(s) that belong to this device.
945	for _, sibkey := range ckf.GetAllActiveSibkeys() {
946		sibkeyKID := sibkey.GetKID()
947		if ckf.cki.KIDToDeviceID[sibkeyKID] == deviceID {
948			ret = append(ret, sibkeyKID)
949			// For each sibkey we find, get all its subkeys too.
950			for _, subkey := range ckf.GetAllActiveSubkeys() {
951				subkeyKID := subkey.GetKID()
952				if ckf.cki.Infos[subkeyKID].Parent.Equal(sibkeyKID) {
953					ret = append(ret, subkeyKID)
954				}
955			}
956		}
957	}
958	return ret, nil
959}
960
961// HasActiveKey returns if the given ComputeKeyFamily has any active keys.
962// The key has to be in the server-given KeyFamily and also in our ComputedKeyFamily.
963// The former check is so that we can handle the case nuked sigchains.
964func (ckf ComputedKeyFamily) HasActiveKey() bool {
965	for kid := range ckf.kf.AllKIDs {
966		if ckf.GetKeyRole(kid) == DLGSibkey {
967			return true
968		}
969	}
970	return false
971}
972
973// GetActivePGPKeys gets the active PGP keys from the ComputedKeyFamily.
974// If sibkey is False it will return all active PGP keys. Otherwise, it
975// will return only the Sibkeys. Note the keys need to be non-canceled,
976// and non-expired.
977func (ckf ComputedKeyFamily) GetActivePGPKeys(sibkey bool) (ret []*PGPKeyBundle) {
978	for kid := range ckf.kf.PGPKeySets {
979		role := ckf.GetKeyRole(kid)
980		if (sibkey && role == DLGSibkey) || role != DLGNone {
981			if key, err := ckf.FindKeyWithKIDUnsafe(kid); err == nil {
982				ret = append(ret, key.(*PGPKeyBundle))
983			} else {
984				ckf.G().Log.Errorf("KID %s was in a KeyFamily's list of PGP keys, but the key doesn't exist: %s", kid, err)
985			}
986		}
987	}
988	return
989}
990
991type RevokedKey struct {
992	Key       GenericKey
993	RevokedAt *KeybaseTime
994	RevokedBy keybase1.KID
995}
996
997func (ckf ComputedKeyFamily) GetRevokedKeys() []RevokedKey {
998	ckf.G().Log.Debug("+ GetRevokedKeys")
999	defer ckf.G().Log.Debug("- GetRevokedKeys")
1000
1001	var revokedKeys []RevokedKey
1002	for kid := range ckf.kf.AllKIDs {
1003		ki, ok := ckf.cki.Infos[kid]
1004		if !ok || ki == nil {
1005			ckf.G().Log.Debug("KID %s not in cki.Infos (likely belongs to a previous subchain). Skipping.", kid)
1006			continue
1007		}
1008		if ki.Status != KeyRevoked {
1009			continue
1010		}
1011		if ki.RevokedAt == nil {
1012			ckf.G().Log.Errorf("KID %s: status is KeyRevoked, but RevokedAt is nil", kid)
1013			continue
1014		}
1015		if ki.RevokedBy.IsNil() {
1016			ckf.G().Log.Debug("KID %s: RevokedAt is non-nil, but RevokedBy is nil, probably just old", kid)
1017		}
1018
1019		key, err := ckf.FindKeyWithKIDUnsafe(kid)
1020		if err != nil {
1021			ckf.G().Log.Errorf("No key found for %s in ckf", kid)
1022			continue
1023		}
1024
1025		revokedKeys = append(revokedKeys, RevokedKey{Key: key, RevokedAt: ki.RevokedAt, RevokedBy: ki.RevokedBy})
1026	}
1027
1028	return revokedKeys
1029}
1030
1031func (ckf ComputedKeyFamily) GetDeletedKeys() []GenericKey {
1032	ckf.G().Log.Debug("+ GetDeletedKeys")
1033	defer ckf.G().Log.Debug("- GetDeletedKeys")
1034
1035	var keys []GenericKey
1036	for kid := range ckf.kf.AllKIDs {
1037		_, ok := ckf.cki.Infos[kid]
1038		if ok {
1039			// key in cki.Infos, so it is in the current subchain, skip it.
1040			continue
1041		}
1042		key, err := ckf.FindKeyWithKIDUnsafe(kid)
1043		if err != nil {
1044			ckf.G().Log.Errorf("No key found for %s in ckf", kid)
1045			continue
1046		}
1047		keys = append(keys, key)
1048	}
1049	return keys
1050}
1051
1052// UpdateDevices takes the Device object from the given ChainLink
1053// and updates keys to reflects any device changes encoded therein.
1054func (ckf *ComputedKeyFamily) UpdateDevices(tcl TypedChainLink) (err error) {
1055
1056	var dobj *Device
1057	if dobj = tcl.GetDevice(); dobj == nil {
1058		ckf.G().VDL.Log(VLog1, "Short-circuit of UpdateDevices(); not a device link")
1059		return
1060	}
1061
1062	defer ckf.G().Trace("UpdateDevice", &err)()
1063
1064	did := dobj.ID
1065	kid := dobj.Kid
1066
1067	ckf.G().Log.Debug("| Device ID=%s; KID=%s", did, kid.String())
1068
1069	var prevKid keybase1.KID
1070	if existing, found := ckf.cki.Devices[did]; found {
1071		ckf.G().Log.Debug("| merge with existing")
1072		prevKid = existing.Kid
1073		existing.Merge(dobj)
1074		dobj = existing
1075	} else {
1076		ckf.G().Log.Debug("| New insert")
1077		ckf.cki.Devices[did] = dobj
1078	}
1079
1080	// If a KID is specified, we should clear out any previous KID from the
1081	// KID->Device map. But if not, leave the map as it is. Later "device"
1082	// blobs in the sigchain aren't required to repeat the KID every time.
1083	if kid.IsValid() {
1084		if prevKid.IsValid() {
1085			ckf.G().Log.Debug("| Clear out old key")
1086			delete(ckf.cki.KIDToDeviceID, prevKid)
1087		}
1088		ckf.cki.KIDToDeviceID[kid] = did
1089	}
1090
1091	return
1092}
1093
1094func (ckf *ComputedKeyFamily) getSibkeyKidForDevice(did keybase1.DeviceID) (keybase1.KID, error) {
1095	ckf.G().Log.Debug("+ getSibkeyKidForDevice(%v)", did)
1096	ckf.G().Log.Debug("| Devices map: %+v", ckf.cki.Devices)
1097
1098	var kid keybase1.KID
1099	device, found := ckf.cki.Devices[did]
1100	if !found {
1101		ckf.G().Log.Debug("device %s not found in cki.Devices", did)
1102		return kid, NoDeviceError{Reason: fmt.Sprintf("for device ID %s", did)}
1103	}
1104	if !device.Kid.IsValid() {
1105		ckf.G().Log.Debug("device found, but Kid invalid")
1106		return kid, fmt.Errorf("invalid kid for device %s", did)
1107	}
1108
1109	ckf.G().Log.Debug("device found, kid: %s", device.Kid.String())
1110	return device.Kid, nil
1111}
1112
1113// GetSibkeyForDevice gets the current per-device key for the given Device. Will
1114// return nil if one isn't found, and set err for a real error. The sibkey should
1115// be a signing key, not an encryption key of course.
1116func (ckf *ComputedKeyFamily) GetSibkeyForDevice(did keybase1.DeviceID) (key GenericKey, err error) {
1117	var kid keybase1.KID
1118	kid, err = ckf.getSibkeyKidForDevice(did)
1119	if kid.Exists() {
1120		key, _, err = ckf.FindActiveSibkey(kid)
1121	}
1122	return
1123}
1124
1125// GetCurrentDevice returns the current device.
1126func (ckf *ComputedKeyFamily) GetCurrentDevice(g *GlobalContext) (*Device, error) {
1127	did := g.Env.GetDeviceID()
1128	if did.IsNil() {
1129		return nil, NotProvisionedError{}
1130	}
1131
1132	dev, ok := ckf.cki.Devices[did]
1133	if !ok {
1134		return nil, NotFoundError{}
1135	}
1136
1137	return dev, nil
1138}
1139
1140// GetEncryptionSubkeyForDevice gets the current encryption subkey for the given device.
1141func (ckf *ComputedKeyFamily) GetEncryptionSubkeyForDevice(did keybase1.DeviceID) (key GenericKey, err error) {
1142	var kid keybase1.KID
1143	if kid, err = ckf.getSibkeyKidForDevice(did); err != nil {
1144		return
1145	}
1146	if kid.IsNil() {
1147		return
1148	}
1149	if cki, found := ckf.cki.Infos[kid]; !found {
1150		return
1151	} else if !cki.Subkey.IsValid() {
1152		return
1153	} else {
1154		key, _, err = ckf.FindActiveEncryptionSubkey(cki.Subkey)
1155	}
1156	return
1157}
1158
1159func (ckf *ComputedKeyFamily) HasActiveEncryptionSubkey() bool {
1160	for kid := range ckf.cki.Infos {
1161		if !kid.IsValid() {
1162			continue
1163		}
1164		if key, _, err := ckf.FindActiveEncryptionSubkey(kid); key != nil && err == nil {
1165			return true
1166		}
1167	}
1168	return false
1169}
1170
1171// GetDeviceForKey gets the device that this key is bound to, if any.
1172func (ckf *ComputedKeyFamily) GetDeviceForKey(key GenericKey) (*Device, error) {
1173	return ckf.GetDeviceForKID(key.GetKID())
1174}
1175
1176func (ckf *ComputedKeyFamily) GetDeviceForKID(kid keybase1.KID) (*Device, error) {
1177	dev, err := ckf.getDeviceForKidHelper(kid)
1178	if err == nil && dev != nil {
1179		return dev, nil
1180	}
1181
1182	// this could be a subkey, so try to find device for the parent
1183	cki, found := ckf.cki.Infos[kid]
1184	if !found {
1185		return nil, NoDeviceError{Reason: fmt.Sprintf("for key ID %s", kid)}
1186	}
1187	parent := cki.Parent
1188	if parent.IsNil() {
1189		return nil, NoDeviceError{Reason: fmt.Sprintf("for key ID %s", kid)}
1190	}
1191
1192	return ckf.getDeviceForKidHelper(parent)
1193
1194}
1195
1196func (ckf *ComputedKeyFamily) getDeviceForKidHelper(kid keybase1.KID) (ret *Device, err error) {
1197	if didString, found := ckf.cki.KIDToDeviceID[kid]; found {
1198		ret = ckf.cki.Devices[didString]
1199	}
1200	return
1201}
1202
1203type byAge []*Device
1204
1205func (a byAge) Len() int           { return len(a) }
1206func (a byAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
1207func (a byAge) Less(i, j int) bool { return a[i].CTime < a[j].CTime }
1208
1209func (ckf *ComputedKeyFamily) GetAllDevices() []DeviceWithDeviceNumber {
1210	devicesNoNum := make([]*Device, 0, len(ckf.cki.Devices))
1211	for _, device := range ckf.cki.Devices {
1212		devicesNoNum = append(devicesNoNum, device)
1213	}
1214	sort.Sort(byAge(devicesNoNum))
1215	devices := make([]DeviceWithDeviceNumber, 0, len(devicesNoNum))
1216	deviceNumMap := make(map[keybase1.DeviceTypeV2]int)
1217	for _, device := range devicesNoNum {
1218
1219		devices = append(devices, DeviceWithDeviceNumber{device, deviceNumMap[device.Type]})
1220
1221		deviceNumMap[device.Type]++
1222	}
1223	return devices
1224}
1225
1226func (ckf *ComputedKeyFamily) GetAllActiveDevices() []DeviceWithDeviceNumber {
1227	devices := make([]DeviceWithDeviceNumber, 0)
1228	for _, device := range ckf.GetAllDevices() {
1229		if device.IsActive() {
1230			devices = append(devices, device)
1231		}
1232	}
1233	return devices
1234}
1235
1236func (ckf *ComputedKeyFamily) HasActiveDevice() bool {
1237	for _, device := range ckf.cki.Devices {
1238		if device.IsActive() {
1239			return true
1240		}
1241	}
1242	return false
1243}
1244
1245// Returns (&senderType, err). A non-nil error indicates some unexpected
1246// condition (like the key doesn't exist at all), which should be propagated.
1247// If the sender type is nil, the key is active, and the caller should proceed
1248// with an identify. Otherwise the key is no longer active, and the sender type
1249// indicates why.
1250func (ckf ComputedKeyFamily) GetSaltpackSenderTypeIfInactive(kid keybase1.KID) (*keybase1.SaltpackSenderType, error) {
1251	info := ckf.cki.Infos[kid]
1252	if info == nil {
1253		// This shouldn't happen without a server bug/attack or a very unlikely
1254		// race condition (e.g. a user account reset between the API server
1255		// telling us they own a key, and the loaduser confirming it.)
1256		return nil, fmt.Errorf("Key %s not found in key infos", kid.String())
1257	}
1258	if info.Status == KeyRevoked {
1259		ret := keybase1.SaltpackSenderType_REVOKED
1260		return &ret, nil
1261	}
1262	if info.Status == KeyUncancelled {
1263		// TODO: Get rid of the whole concept of expiration?
1264		if info.GetETime().Before(time.Now()) && !info.GetETime().IsZero() {
1265			ret := keybase1.SaltpackSenderType_EXPIRED
1266			return &ret, nil
1267		}
1268		// An active key. The caller needs to do an identify to determine the
1269		// final sender type (UNTRACKED, TRACKING_BROKE, etc.).
1270		return nil, nil
1271	}
1272	// This also shouldn't happen without a server bug or a very unlikely race
1273	// condition.
1274	return nil, fmt.Errorf("Key %s neither active nor revoked (%d)", kid.String(), info.Status)
1275}
1276
1277// If there aren't any per-user-keys for the user, return nil.
1278func (ckf *ComputedKeyFamily) GetLatestPerUserKey() *keybase1.PerUserKey {
1279	var currentGeneration keybase1.PerUserKeyGeneration
1280	var ret *keybase1.PerUserKey
1281	if ckf == nil {
1282		panic("nil ckf") // with a nil ckf, we can't log and this method will crash anyway.
1283	}
1284	if ckf.cki == nil {
1285		ckf.G().Log.Debug("ComputedKeyFamily#GetLatestPerUserKey: nil cki")
1286	}
1287	for generation, key := range ckf.cki.PerUserKeys {
1288		if generation > currentGeneration {
1289			currentGeneration = generation
1290			// Avoid taking references to the loop variable.
1291			currentKey := key
1292			ret = &currentKey
1293		}
1294	}
1295	return ret
1296}
1297