github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libkb/keyfamily.go (about) 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. 7 package libkb 8 9 import ( 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. 26 type KeybaseTime struct { 27 Unix int64 // UTC wallclock time 28 Chain keybase1.Seqno // Merkle root chain time 29 } 30 31 // Struct for the DelegationsList 32 type Delegation struct { 33 KID keybase1.KID 34 SigID keybase1.SigID 35 } 36 37 type ComputedKeyInfosVersion int 38 39 const ( 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. 48 type 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 97 func (cki ComputedKeyInfo) GetCTime() time.Time { 98 return time.Unix(cki.CTime, 0) 99 } 100 101 func (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 108 type 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 136 type 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. 143 type PGPKeySet struct { 144 Contextified 145 PermissivelyMergedKey *PGPKeyBundle 146 KeysByHash map[string]*PGPKeyBundle 147 } 148 149 func (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 189 type 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. 209 type 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. 217 func (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. 223 func (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 . 242 func (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 276 func (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 309 func (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 322 func 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 334 func 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 347 func (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. 356 func (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 378 func (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. 420 func 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. 489 func (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 507 func (ckf ComputedKeyFamily) getCkiUnchecked(kid keybase1.KID) (ret *ComputedKeyInfo) { 508 return ckf.cki.Infos[kid] 509 } 510 511 func (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 528 func (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. 537 func (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. 545 func (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. 562 func (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 580 func (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. 590 func 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 599 func 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. 608 func (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 634 func (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" 642 func (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 681 func (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. 686 func (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. 708 func (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 717 func (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. 738 func (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. 748 func (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. 762 func (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 773 func (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 804 func (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. 828 func (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. 847 func (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. 858 func (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. 872 func (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. 878 func (ckf ComputedKeyFamily) GetAllSubkeysUnchecked() (ret []GenericKey) { 879 return ckf.getAllKeysUnchecked(DLGSubkey) 880 } 881 882 func (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. 898 func (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. 903 func (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. 921 func (ckf ComputedKeyFamily) GetAllActiveSibkeysAtTime(t time.Time) []GenericKey { 922 return ckf.GetAllActiveKeysWithRoleAtTime(DLGSibkey, t) 923 } 924 925 // GetAllActiveSibkeys gets all active Sibkeys from given ComputedKeyFamily. 926 func (ckf ComputedKeyFamily) GetAllActiveSibkeys() []GenericKey { 927 return ckf.GetAllActiveSibkeysAtTime(time.Now()) 928 } 929 930 func (ckf ComputedKeyFamily) GetAllActiveSubkeysAtTime(t time.Time) (ret []GenericKey) { 931 return ckf.GetAllActiveKeysWithRoleAtTime(DLGSubkey, t) 932 } 933 934 func (ckf ComputedKeyFamily) GetAllActiveSubkeys() []GenericKey { 935 return ckf.GetAllActiveSubkeysAtTime(time.Now()) 936 } 937 938 func (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. 964 func (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. 977 func (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 991 type RevokedKey struct { 992 Key GenericKey 993 RevokedAt *KeybaseTime 994 RevokedBy keybase1.KID 995 } 996 997 func (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 1031 func (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. 1054 func (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 1094 func (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. 1116 func (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. 1126 func (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. 1141 func (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 1159 func (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. 1172 func (ckf *ComputedKeyFamily) GetDeviceForKey(key GenericKey) (*Device, error) { 1173 return ckf.GetDeviceForKID(key.GetKID()) 1174 } 1175 1176 func (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 1196 func (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 1203 type byAge []*Device 1204 1205 func (a byAge) Len() int { return len(a) } 1206 func (a byAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 1207 func (a byAge) Less(i, j int) bool { return a[i].CTime < a[j].CTime } 1208 1209 func (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 1226 func (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 1236 func (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. 1250 func (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. 1278 func (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 = ¤tKey 1293 } 1294 } 1295 return ret 1296 }