github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libkb/sig_chain.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 package libkb 5 6 import ( 7 "errors" 8 "fmt" 9 "io" 10 "time" 11 12 "github.com/buger/jsonparser" 13 "github.com/keybase/client/go/jsonparserw" 14 keybase1 "github.com/keybase/client/go/protocol/keybase1" 15 ) 16 17 type ChainLinks []*ChainLink 18 19 // 20 // As of Sigchain V2, there are 3 types of sigchain links you might 21 // encounter. 22 // 23 // V1 AKA Inner: The original sigchain link is a JSON blob describing 24 // the signer's eldest key, signing key, payload, and prev pointers, 25 // among other fields. As we migrate to sigchain V2, this is known as the 26 // "inner" link. It persists in some cases and is elided for bandwidth 27 // savings in others. 28 // 29 // V2 AKA Outer/Inner Split: In V2, the signer computes a signature over 30 // a much smaller outer link (see OuterLinkV2 in chain_link_v2.go). The 31 // "curr" field in the outer link points to a V1 inner link by content hash. 32 // Essential fields from the V1 inner link are hoisted up into the V2 outer 33 // link and therefore must agree. Thus, the "prev" pointer in the V2 outer 34 // link is the same as the "prev" pointer in the V2 inner link; it equals 35 // the "curr" pointer of the previous outer link. 36 // 37 // V2 Stubbed: To save bandwidth, the server is allowed to send over just 38 // the V2 Outer link, minus any signatures, minus an inner link, if the 39 // consuming client can safely ignore those details. 40 // 41 42 type BaseSigChain interface { 43 VerifyChain(m MetaContext) (err error) 44 GetComputedKeyInfos() (cki *ComputedKeyInfos) 45 } 46 type SigChain struct { 47 Contextified 48 49 uid keybase1.UID 50 username NormalizedUsername 51 chainLinks ChainLinks // all the links we know about, starting with seqno 1 52 loadedFromLinkOne bool 53 wasFullyCached bool 54 55 // If we've locally delegated a key, it won't be reflected in our 56 // loaded chain, so we need to make a note of it here. 57 localCki *ComputedKeyInfos 58 59 // If we've made local modifications to our chain, mark it here; 60 // there's a slight lag on the server and we might not get the 61 // new chain tail if we query the server right after an update. 62 localChainTail *MerkleTriple 63 localChainNextHighSkipOverride *HighSkip 64 65 // When the local chains were updated. 66 localChainUpdateTime time.Time 67 68 // The sequence number of the first chain link in the current subchain. For 69 // a user who has never done a reset, this is 1. Note that if the user has 70 // done a reset (or just created a fresh account) but not yet made any 71 // signatures, this seqno refers to a link that doesn't yet exist. 72 currentSubchainStart keybase1.Seqno 73 74 // In some cases, it is useful to load all existing subchains for this user. 75 // If so, they will be slotted into this slice. 76 prevSubchains []ChainLinks 77 } 78 79 func (sc SigChain) Len() int { 80 return len(sc.chainLinks) 81 } 82 83 func (c ChainLinks) EldestSeqno() keybase1.Seqno { 84 if len(c) == 0 { 85 return keybase1.Seqno(0) 86 } 87 return c[0].GetSeqno() 88 } 89 90 func (sc *SigChain) LocalDelegate(kf *KeyFamily, key GenericKey, sigID keybase1.SigID, signingKid keybase1.KID, isSibkey bool, mhm keybase1.HashMeta, fau keybase1.Seqno) (err error) { 91 92 sc.G().Log.Debug("SigChain#LocalDelegate(key: %s, sigID: %s, signingKid: %s, isSibkey: %v)", key.GetKID(), sigID, signingKid, isSibkey) 93 94 cki := sc.localCki 95 l := sc.GetLastLink() 96 if cki == nil && l != nil && l.cki != nil { 97 // TODO: Figure out whether this needs to be a deep copy. See 98 // https://github.com/keybase/client/issues/414 . 99 cki = l.cki.ShallowCopy() 100 } 101 if cki == nil { 102 sc.G().Log.Debug("LocalDelegate: creating new cki (signingKid: %s)", signingKid) 103 cki = NewComputedKeyInfos(sc.G()) 104 cki.InsertLocalEldestKey(signingKid) 105 } 106 107 // Update the current state 108 sc.localCki = cki 109 110 if len(sigID) > 0 { 111 var zeroTime time.Time 112 err = cki.Delegate(key.GetKID(), NowAsKeybaseTime(0), sigID, signingKid, signingKid, "" /* pgpHash */, isSibkey, time.Unix(0, 0), zeroTime, mhm, fau, keybase1.SigChainLocation{}) 113 } 114 115 return 116 } 117 118 func (sc *SigChain) LocalDelegatePerUserKey(perUserKey keybase1.PerUserKey) error { 119 120 cki := sc.localCki 121 l := sc.GetLastLink() 122 if cki == nil && l != nil && l.cki != nil { 123 // TODO: Figure out whether this needs to be a deep copy. See 124 // https://github.com/keybase/client/issues/414 . 125 cki = l.cki.ShallowCopy() 126 } 127 if cki == nil { 128 return errors.New("LocalDelegatePerUserKey: no computed key info") 129 } 130 131 // Update the current state 132 sc.localCki = cki 133 134 err := cki.DelegatePerUserKey(perUserKey) 135 return err 136 } 137 138 func (sc *SigChain) EldestSeqno() keybase1.Seqno { 139 return sc.currentSubchainStart 140 } 141 142 func (c ChainLinks) GetComputedKeyInfos() (cki *ComputedKeyInfos) { 143 ll := last(c) 144 if ll == nil { 145 return nil 146 } 147 return ll.cki 148 } 149 150 func (sc SigChain) GetComputedKeyInfos() (cki *ComputedKeyInfos) { 151 cki = sc.localCki 152 if cki == nil { 153 if l := sc.GetLastLink(); l != nil { 154 if l.cki == nil { 155 sc.G().Log.Debug("GetComputedKeyInfos: l.cki is nil") 156 } 157 cki = l.cki 158 } 159 } 160 return 161 } 162 163 func (sc SigChain) GetComputedKeyInfosWithVersionBust() (cki *ComputedKeyInfos) { 164 ret := sc.GetComputedKeyInfos() 165 if ret == nil { 166 return ret 167 } 168 if ret.IsStaleVersion() { 169 sc.G().Log.Debug("Threw out CKI due to stale version (%d)", ret.Version) 170 ret = nil 171 } 172 return ret 173 } 174 175 func (sc SigChain) GetFutureChainTail() (ret *MerkleTriple) { 176 now := sc.G().Clock().Now() 177 if sc.localChainTail != nil && now.Sub(sc.localChainUpdateTime) < ServerUpdateLag { 178 ret = sc.localChainTail 179 } 180 return 181 } 182 183 func reverse(links ChainLinks) { 184 for i, j := 0, len(links)-1; i < j; i, j = i+1, j-1 { 185 links[i], links[j] = links[j], links[i] 186 } 187 } 188 189 func first(links ChainLinks) (ret *ChainLink) { 190 if len(links) == 0 { 191 return nil 192 } 193 return links[0] 194 } 195 196 func last(links ChainLinks) (ret *ChainLink) { 197 if len(links) == 0 { 198 return nil 199 } 200 return links[len(links)-1] 201 } 202 203 func (sc *SigChain) VerifiedChainLinks(fp PGPFingerprint) (ret ChainLinks) { 204 last := sc.GetLastLink() 205 if last == nil || !last.sigVerified { 206 return nil 207 } 208 start := -1 209 for i := len(sc.chainLinks) - 1; i >= 0 && sc.chainLinks[i].MatchFingerprint(fp); i-- { 210 start = i 211 } 212 if start >= 0 { 213 ret = sc.chainLinks[start:] 214 } 215 return ret 216 } 217 218 // Bump updates the latest seqno and high skip pointers during 219 // multisig posts. isHighDelegator is true iff the sig making 220 // causing the bump is high (e.g., for a sibkey). 221 func (sc *SigChain) Bump(mt MerkleTriple, isHighDelegator bool) { 222 mt.Seqno = sc.GetLastKnownSeqno() + 1 223 sc.G().Log.Debug("| Bumping SigChain LastKnownSeqno to %d", mt.Seqno) 224 sc.localChainTail = &mt 225 sc.localChainUpdateTime = sc.G().Clock().Now() 226 if isHighDelegator { 227 highSkip := NewHighSkip(mt.Seqno, mt.LinkID) 228 sc.localChainNextHighSkipOverride = &highSkip 229 } 230 } 231 232 type sigCompression3Type int 233 234 const ( 235 sigCompression3Unstubbed sigCompression3Type = 1 236 sigCompression3Stubbed sigCompression3Type = 2 237 ) 238 239 func (sc *SigChain) LoadFromServer(m MetaContext, t *MerkleTriple, selfUID keybase1.UID, stubMode StubMode, unstubs map[keybase1.Seqno]LinkID) (dirtyTail *MerkleTriple, err error) { 240 m, tbs := m.WithTimeBuckets() 241 low := sc.GetLastLoadedSeqno() 242 lenPrev := sc.Len() 243 sc.loadedFromLinkOne = (low == keybase1.Seqno(0) || low == keybase1.Seqno(-1)) 244 245 m.Debug("+ Load SigChain from server (uid=%s, low=%d)", sc.uid, low) 246 defer func() { m.Debug("- Loaded SigChain -> %s", ErrToOk(err)) }() 247 248 // Signal if you want to read deleted sig chains for debugging, requires 249 // admin permissions to be honored on the server. 250 readDeleted := m.G().Env.GetReadDeletedSigChain() 251 252 c3 := sigCompression3Unstubbed 253 if stubMode == StubModeStubbed { 254 c3 = sigCompression3Stubbed 255 } 256 257 resp, finisher, err := sc.G().API.GetResp(m, APIArg{ 258 Endpoint: "sig/get", 259 SessionType: APISessionTypeOPTIONAL, 260 Args: HTTPArgs{ 261 "uid": UIDArg(sc.uid), 262 "low": I{int(low)}, 263 "read_deleted": B{readDeleted}, 264 "c3": I{int(c3)}, 265 }, 266 }) 267 if err != nil { 268 return 269 } 270 defer finisher() 271 272 recordFin := tbs.Record("SigChain.LoadFromServer.ReadAll") 273 body, err := io.ReadAll(resp.Body) 274 if err != nil { 275 recordFin() 276 return nil, err 277 } 278 recordFin() 279 dirtyTail, err = sc.LoadServerBody(m, body, low, t, selfUID) 280 if err != nil { 281 return nil, err 282 } 283 err = sc.checkUnstubs(lenPrev, unstubs) 284 if err != nil { 285 return nil, err 286 } 287 return dirtyTail, nil 288 } 289 290 func (sc *SigChain) LoadServerBody(m MetaContext, body []byte, low keybase1.Seqno, t *MerkleTriple, selfUID keybase1.UID) (dirtyTail *MerkleTriple, err error) { 291 // NOTE: This status only gets set from the server if the requesting user 292 // has not interacted with the deleted user. The idea being if you have 293 // interacted (chatted, etc) with this user you should still verify their 294 // sigchain. Otherwise you can ignore it. 295 var val int64 296 val, err = jsonparserw.GetInt(body, "status", "code") 297 298 // Server should always reply with a valid status code 299 if err != nil { 300 return nil, err 301 } 302 303 if keybase1.StatusCode(val) == keybase1.StatusCode_SCDeleted { 304 // Do not bother trying to read the sigchain - user is 305 // deleted. 306 return nil, UserDeletedError{} 307 } 308 309 if keybase1.StatusCode(val) != keybase1.StatusCode_SCOk { 310 m.Debug("SigChain#LoadServerBody: got unexpected status code (%d) but continuing", val) 311 } 312 313 foundTail := false 314 315 var links ChainLinks 316 var tail *ChainLink 317 318 numEntries := 0 319 var travErr error 320 var linkErr error 321 322 _, travErr = jsonparserw.ArrayEach(body, func(value []byte, dataType jsonparser.ValueType, offset int, inErr error) { 323 324 var link *ChainLink 325 var tmpErr error 326 327 // MK (2020.03.09): This error is actually never generated by buger/jsonparse, but 328 // maybe that might change in the future. If so, let's handle it. 329 if inErr != nil { 330 m.Debug("ImportLinkFromServer: jsonparser failed with error %s", inErr) 331 linkErr = inErr 332 return 333 } 334 335 // NOTE: there isn't a good way to signal to ArrayEach to early-out of the traversal. 336 // If we do hit such an error, we set linkErr with the last-error wins strategy. 337 // And any linkErr being set is enough to kill the chain reconstruction. 338 link, tmpErr = ImportLinkFromServer(m, sc, value, selfUID) 339 if tmpErr != nil { 340 m.Debug("ImportLinkFromServer error at link %d: %s", numEntries+1, tmpErr) 341 linkErr = tmpErr 342 return 343 } 344 345 if link.GetSeqno() <= low { 346 return 347 } 348 349 // After we know it's not a dupe, let's put the link to cache. 350 putLinkToCache(m, link) 351 352 if selfUID.Equal(link.GetUID()) { 353 m.Debug("| Setting isOwnNewLinkFromServer=true for seqno %d", link.GetSeqno()) 354 link.isOwnNewLinkFromServer = true 355 } 356 links = append(links, link) 357 358 // If haven't found a tail yet, and we got a triple from the server, and the 359 // link isn't stubbed, then let's check this link against what we got from the 360 // tree. This might generate a failure (if the hashes clash) or just a "not found" 361 // which is something we can try again in a future link. Note that there could be a race 362 // between when we asked the tree for the tail, and when we fetched the chainlinks, 363 // so we can't just check the last link, we need to check all. 364 if !foundTail && t != nil && !link.IsStubbed() { 365 foundTail, tmpErr = link.checkAgainstMerkleTree(t) 366 if tmpErr != nil { 367 m.Debug("checkAgainstMerkleTree failure error at link %d: %s", numEntries+1, tmpErr) 368 linkErr = tmpErr 369 return 370 } 371 } 372 tail = link 373 numEntries++ 374 }, "sigs") 375 376 // We hit this error condition if there was an error iterating through the chain above. 377 // Note that ArrayEach doesn't allow a better to propagate an error, so we use this locally 378 // scoped error to signal that one of the links failed to import. Last writer wins here. 379 if linkErr != nil { 380 m.Debug("SigChain#LoadServerBody: failing due to bad chainlink: %s", linkErr) 381 return nil, err 382 } 383 384 // travErr is generated when ArrayEach hit a failure (not the callback we pass to it). 385 // We'll get this if the JSON the server sent back is broken or malformed. 386 if travErr != nil { 387 m.Debug("SigChain#LoadServerBody: traverse error: %s", travErr) 388 return nil, travErr 389 } 390 391 m.Debug("| Got back %d new entries", numEntries) 392 393 if t != nil && !foundTail { 394 err = NewServerChainError("Failed to reach (%s, %d) in server response", 395 t.LinkID, int(t.Seqno)) 396 return nil, err 397 } 398 399 if tail != nil { 400 dirtyTail = tail.ToMerkleTriple() 401 402 // If we've stored a `last` and it's less than the one 403 // we just loaded, then nuke it. 404 if sc.localChainTail != nil && sc.localChainTail.Less(*dirtyTail) { 405 m.Debug("| Clear cached last (%d < %d)", sc.localChainTail.Seqno, dirtyTail.Seqno) 406 sc.localChainTail = nil 407 sc.localChainNextHighSkipOverride = nil 408 sc.localCki = nil 409 } 410 } 411 412 sc.chainLinks = append(sc.chainLinks, links...) 413 return dirtyTail, nil 414 } 415 416 func (sc *SigChain) SetUIDUsername(uid keybase1.UID, username string) { 417 sc.uid = uid 418 sc.username = NewNormalizedUsername(username) 419 } 420 421 func (sc *SigChain) getFirstSeqno() (ret keybase1.Seqno) { 422 if len(sc.chainLinks) > 0 { 423 ret = sc.chainLinks[0].GetSeqno() 424 } 425 return ret 426 } 427 428 func (sc *SigChain) VerifyChain(mctx MetaContext, uid keybase1.UID) (err error) { 429 defer mctx.Trace(fmt.Sprintf("SigChain#VerifyChain(%s)", uid), &err)() 430 defer mctx.PerfTrace(fmt.Sprintf("SigChain#VerifyChain(%s)", uid), &err)() 431 start := time.Now() 432 defer func() { 433 var message string 434 if err == nil { 435 message = fmt.Sprintf("Verified sig chain for %s", uid) 436 } else { 437 message = fmt.Sprintf("Failed to verify sigchain for %s", uid) 438 } 439 mctx.G().RuntimeStats.PushPerfEvent(keybase1.PerfEvent{ 440 EventType: keybase1.PerfEventType_USERCHAIN, 441 Message: message, 442 Ctime: keybase1.ToTime(start), 443 }) 444 }() 445 446 expectedNextHighSkip := NewInitialHighSkip() 447 firstUnverifiedChainIdx := 0 448 outer: 449 for i := len(sc.chainLinks) - 1; i >= 0; i-- { 450 curr := sc.chainLinks[i] 451 mctx.VLogf(VLog1, "| verify link %d (%s)", i, curr.id) 452 if curr.chainVerified { 453 expectedNextHighSkipPre, err := curr.ExpectedNextHighSkip(mctx, uid) 454 455 switch err.(type) { 456 case UserReverifyNeededError: 457 mctx.Debug("Continuing verification at link %d due to uncomputed high skip.", i) 458 case nil: 459 mctx.Debug("| short-circuit at link %d", i) 460 expectedNextHighSkip = expectedNextHighSkipPre 461 firstUnverifiedChainIdx = i + 1 462 break outer 463 default: 464 return err 465 } 466 } 467 if err = curr.VerifyLink(); err != nil { 468 return err 469 } 470 if i > 0 { 471 prev := sc.chainLinks[i-1] 472 // NB: In a sigchain v2 link, `id` refers to the hash of the 473 // *outer* link, not the hash of the v1-style inner payload. 474 if !prev.id.Eq(curr.GetPrev()) { 475 return ChainLinkPrevHashMismatchError{fmt.Sprintf("Chain mismatch at seqno=%d", curr.GetSeqno())} 476 } 477 if prev.GetSeqno()+1 != curr.GetSeqno() { 478 return ChainLinkWrongSeqnoError{fmt.Sprintf("Chain seqno mismatch at seqno=%d (previous=%d)", curr.GetSeqno(), prev.GetSeqno())} 479 } 480 } 481 if err = curr.CheckNameAndID(sc.username, sc.uid); err != nil { 482 return err 483 } 484 curr.markChainVerified() 485 } 486 487 for i := firstUnverifiedChainIdx; i < len(sc.chainLinks); i++ { 488 curr := sc.chainLinks[i] 489 curr.computedHighSkip = &expectedNextHighSkip 490 491 // If the sigchain claims an HighSkip, make sure it matches our 492 // computation. 493 if highSkip := curr.GetHighSkip(); highSkip != nil { 494 err = highSkip.AssertEqualsExpected(*curr.computedHighSkip) 495 if err != nil { 496 return err 497 } 498 } 499 expectedNextHighSkip, err = curr.ExpectedNextHighSkip(mctx, uid) 500 if err != nil { 501 return err 502 } 503 } 504 505 return err 506 } 507 508 func (sc SigChain) GetCurrentTailTriple() (ret *MerkleTriple) { 509 if l := sc.GetLastLink(); l != nil { 510 ret = l.ToMerkleTriple() 511 } 512 return 513 } 514 515 func (sc SigChain) GetLastLoadedID() (ret LinkID) { 516 if l := last(sc.chainLinks); l != nil { 517 ret = l.id 518 } 519 return 520 } 521 522 func (sc SigChain) GetLastKnownID() (ret LinkID) { 523 if sc.localChainTail != nil { 524 ret = sc.localChainTail.LinkID 525 } else { 526 ret = sc.GetLastLoadedID() 527 } 528 return 529 } 530 531 // GetExpectedNextHighSkip returns the HighSkip expected for a new link to be 532 // added to the chain. It can only be called after VerifyChain is completed. 533 func (sc SigChain) GetExpectedNextHighSkip(mctx MetaContext, uid keybase1.UID) (HighSkip, error) { 534 if sc.localChainNextHighSkipOverride != nil { 535 return *sc.localChainNextHighSkipOverride, nil 536 } 537 if len(sc.chainLinks) == 0 { 538 return NewInitialHighSkip(), nil 539 } 540 return sc.GetLastLink().ExpectedNextHighSkip(mctx, uid) 541 } 542 543 func (sc SigChain) GetFirstLink() *ChainLink { 544 return first(sc.chainLinks) 545 } 546 547 func (sc SigChain) GetLastLink() *ChainLink { 548 return last(sc.chainLinks) 549 } 550 551 func (sc SigChain) GetLastKnownSeqno() (ret keybase1.Seqno) { 552 sc.G().Log.Debug("+ GetLastKnownSeqno()") 553 defer func() { 554 sc.G().Log.Debug("- GetLastKnownSeqno() -> %d", ret) 555 }() 556 if sc.localChainTail != nil { 557 sc.G().Log.Debug("| Cached in last summary object...") 558 ret = sc.localChainTail.Seqno 559 } else { 560 ret = sc.GetLastLoadedSeqno() 561 } 562 return 563 } 564 565 func (sc SigChain) GetLastLoadedSeqno() (ret keybase1.Seqno) { 566 sc.G().Log.Debug("+ GetLastLoadedSeqno()") 567 defer func() { 568 sc.G().Log.Debug("- GetLastLoadedSeqno() -> %d", ret) 569 }() 570 if l := last(sc.chainLinks); l != nil { 571 sc.G().Log.Debug("| Fetched from main chain") 572 ret = l.GetSeqno() 573 } 574 return 575 } 576 577 func (sc *SigChain) Store(m MetaContext) (err error) { 578 for i := len(sc.chainLinks) - 1; i >= 0; i-- { 579 link := sc.chainLinks[i] 580 var didStore bool 581 if didStore, err = link.Store(m); err != nil || !didStore { 582 return err 583 } 584 select { 585 case <-m.Ctx().Done(): 586 return m.Ctx().Err() 587 default: 588 } 589 } 590 return nil 591 } 592 593 func (sc *SigChain) checkUnstubs(low int, unstubs map[keybase1.Seqno]LinkID) error { 594 595 if unstubs == nil { 596 return nil 597 } 598 599 hits := make(map[keybase1.Seqno]bool) 600 for _, link := range sc.chainLinks[low:] { 601 q := link.GetSeqno() 602 if id, found := unstubs[q]; found && !id.Eq(link.id) { 603 return NewChainLinkBadUnstubError(fmt.Sprintf("Bad unstub for seqno %d: %s != %s", link.GetSeqno(), id, link.id)) 604 } 605 hits[q] = true 606 } 607 for q := range unstubs { 608 if !hits[q] { 609 return NewChainLinkBadUnstubError(fmt.Sprintf("Expected seqno=%d to be unstubbed, but it wasn't", q)) 610 } 611 } 612 613 return nil 614 } 615 616 // Some users (6) managed to reuse eldest keys after a sigchain reset, without 617 // using the "eldest" link type, before the server prohibited this. To clients, 618 // that means their chains don't appear to reset. We hardcode these cases. 619 const resetReason = "hardcoded reset" 620 621 var hardcodedResets = map[keybase1.LinkID]SpecialChainLink{ 622 "f6dae096194690cfee8974b0e10a99ecac2cc8e4f9383516a1f626f614e566e0": {UID: keybase1.UID("2d5c41137d7d9108dbdaa2160ba7e200"), Seqno: keybase1.Seqno(11), Reason: resetReason}, 623 "8d7c1a0c99186f972afc5d3624aca2f88ddc3a5dbf84e826ef0b520c31a78aa3": {UID: keybase1.UID("f1c263462dd526695c458af924977719"), Seqno: keybase1.Seqno(8), Reason: resetReason}, 624 "b489635b4243ef80836a0c4515ed7e30e146f0041704931df280c72e28e9d0fe": {UID: keybase1.UID("8dbf0f1617e285befa93d3da54b68419"), Seqno: keybase1.Seqno(8), Reason: resetReason}, 625 "bc898feeb7a2717e23dc1f457dc18902fb9157bf86374b2a0b1aaba4f2831bee": {UID: keybase1.UID("372c1cbd72e4f851a74d232478a72319"), Seqno: keybase1.Seqno(2), Reason: resetReason}, 626 "91cb1b2c3c76d2ad54be47b034a3f544da9ea8405f6eb68a929ef5fb98914436": {UID: keybase1.UID("12e124d5d1ff6179f3aab88100b93d19"), Seqno: keybase1.Seqno(5), Reason: resetReason}, 627 "af381fd3a43e22edc2ac1f271e3270b92038e4a820de335d179d34eb780f8796": {UID: keybase1.UID("a07089770463db10994c8727177eef19"), Seqno: keybase1.Seqno(12), Reason: resetReason}, 628 } 629 630 // GetCurrentSubchain takes the given sigchain and walks backward until it 631 // finds the start of the current subchain, returning all the links in the 632 // subchain. See isSubchainStart for the details of the logic here. 633 func (sc *SigChain) GetCurrentSubchain(m MetaContext, eldest keybase1.KID) (ChainLinks, error) { 634 return cropToRightmostSubchain(m, sc.chainLinks, eldest, sc.uid) 635 } 636 637 // cropToRightmostSubchain takes the given set of chain links, and then limits the tail 638 // of the chain to just those that correspond to the eldest key given by `eldest`. 639 func cropToRightmostSubchain(m MetaContext, links []*ChainLink, eldest keybase1.KID, uid keybase1.UID) (ChainLinks, error) { 640 // Check for a totally empty chain (that is, a totally new account). 641 if len(links) == 0 { 642 return nil, nil 643 } 644 // Confirm that the last link is not stubbed. This would prevent us from 645 // reading the eldest_kid, so the server should never do it. 646 lastLink := links[len(links)-1] 647 if lastLink.IsStubbed() { 648 return nil, errors.New("the last chain link is unexpectedly stubbed in GetCurrentSunchain") 649 } 650 // Check whether the eldest KID doesn't match the latest link. That means 651 // the account has just been reset, and so as with a new account, there is 652 // no current subchain. 653 if !lastLink.ToEldestKID().Equal(eldest) { 654 return nil, nil 655 } 656 // The usual case: The eldest kid we're looking for matches the latest 657 // link, and we need to loop backwards through every pair of links we have. 658 // If we find a subchain start, return that subslice of links. 659 for i := len(links) - 1; i > 0; i-- { 660 curr := links[i] 661 prev := links[i-1] 662 isStart, err := isSubchainStart(m, curr, prev, uid) 663 if err != nil { 664 return nil, err 665 } 666 if isStart { 667 return links[i:], nil 668 } 669 } 670 // If we didn't find a start anywhere in the middle of the chain, then this 671 // user has no resets, and we'll return the whole chain. Sanity check that 672 // we actually loaded everything back to seqno 1. (Anything else would be 673 // some kind of bug in chain loading.) 674 if links[0].GetSeqno() != 1 { 675 return nil, errors.New("chain ended unexpectedly before seqno 1 in GetCurrentSubchain") 676 } 677 678 // In this last case, we're returning the whole chain. 679 return links, nil 680 } 681 682 // When we're *in the middle of a subchain* (see the note below), there are 683 // four ways we can tell that a link is the start of a new subchain: 684 // 1. The link is seqno 1, the very first link the user ever makes. 685 // 2. The link has the type "eldest". Modern seqno 1 links and sigchain resets 686 // take this form, but old ones don't. 687 // 3. The link has a new eldest kid relative to the one that came before. In 688 // the olden days, all sigchain resets were of this form. Note that oldest 689 // links didn't have the eldest_kid field at all, so the signing kid was 690 // assumed to be the eldest. 691 // 4. One of a set of six hardcoded links that made it in back when case 3 was 692 // the norm, but we forgot to prohibit reusing the same eldest key. We figured 693 // out this set from server data, once we noticed the mistake. 694 // 695 // Note: This excludes cases where a subchain has length zero, either because 696 // the account is totally new, or because it just did a reset but has no new 697 // links (as reflected in the eldest kid we get from the merkle tree). 698 // Different callers handle those cases differently. (Loading the sigchain from 699 // local cache happens before we get the merkle leaf, for example, and so it 700 // punts reset-after-latest-link detection to the server loading step). 701 func isSubchainStart(m MetaContext, currentLink *ChainLink, prevLink *ChainLink, uid keybase1.UID) (bool, error) { 702 // case 1 -- unlikely to be hit in practice, because prevLink would be nil 703 if currentLink.GetSeqno() == 1 { 704 return true, nil 705 } 706 // case 2 707 if currentLink.IsEldest() { 708 return true, nil 709 } 710 // case 2.5: The signatures in cases 3 and 4 are very old, from long before 711 // v2 sigs were introduced. If either the current or previous sig is v2, 712 // short circuit here. This is important because stubbed links (introduced 713 // with v2) break the eldest_kid check for case 3. 714 if currentLink.unpacked.sigVersion > KeybaseSignatureV1 || prevLink.unpacked.sigVersion > KeybaseSignatureV1 { 715 return false, nil 716 } 717 // case 3 718 if !currentLink.ToEldestKID().Equal(prevLink.ToEldestKID()) { 719 return true, nil 720 } 721 722 // case 4 723 found, _, err := currentLink.checkSpecialLinksTable(hardcodedResets, uid, "harcoded resets") 724 if err != nil { 725 m.Warning("Error in isSubchainStart: %s", err.Error()) 726 return false, err 727 } 728 if found { 729 m.Debug("Sigchain playback hit hardcoded reset at %s for %s", currentLink.LinkID(), uid) 730 } 731 return found, nil 732 } 733 734 // Dump prints the sigchain to the writer arg. 735 func (sc *SigChain) Dump(w io.Writer) { 736 fmt.Fprintf(w, "sigchain dump\n") 737 for i, l := range sc.chainLinks { 738 fmt.Fprintf(w, "link %d: %+v\n", i, l) 739 } 740 fmt.Fprintf(w, "last known seqno: %d\n", sc.GetLastKnownSeqno()) 741 fmt.Fprintf(w, "last known id: %s\n", sc.GetLastKnownID()) 742 } 743 744 // verifySubchain verifies the given subchain and outputs a yes/no answer 745 // on whether or not it's well-formed, and also yields ComputedKeyInfos for 746 // all keys found in the process, including those that are now retired. 747 func verifySubchain(m MetaContext, un NormalizedUsername, kf KeyFamily, links ChainLinks) (cached bool, cki *ComputedKeyInfos, err error) { 748 749 m.Debug("+ verifySubchain") 750 defer func() { 751 m.Debug("- verifySubchain -> %v, %s", cached, ErrToOk(err)) 752 }() 753 754 if len(links) == 0 { 755 err = InternalError{"verifySubchain should never get an empty chain."} 756 return cached, cki, err 757 } 758 759 last := links[len(links)-1] 760 if cki = last.GetSigCheckCache(); cki != nil { 761 if cki.IsStaleVersion() { 762 m.Debug("Ignoring cached CKI, since the version is old (%d < %d)", cki.Version, ComputedKeyInfosVersionCurrent) 763 } else { 764 cached = true 765 m.Debug("Skipped verification (cached): %s", last.id) 766 return cached, cki, err 767 } 768 } 769 770 cki = NewComputedKeyInfos(m.G()) 771 ckf := ComputedKeyFamily{kf: &kf, cki: cki, Contextified: NewContextified(m.G())} 772 773 first := true 774 seenInflatedWalletStellarLink := false 775 776 for linkIndex, link := range links { 777 isBad, reason, err := link.IsBad() 778 if err != nil { 779 return cached, cki, err 780 } 781 if isBad { 782 m.Debug("Ignoring bad chain link with link ID %s: %s", link.LinkID(), reason) 783 continue 784 } 785 786 if link.IsStubbed() { 787 if first { 788 return cached, cki, SigchainV2StubbedFirstLinkError{} 789 } 790 if !link.AllowStubbing() { 791 return cached, cki, SigchainV2StubbedSignatureNeededError{} 792 } 793 linkTypeV2, err := link.GetSigchainV2TypeFromV2Shell() 794 if err != nil { 795 return cached, cki, err 796 } 797 if linkTypeV2 == SigchainV2TypeWalletStellar && seenInflatedWalletStellarLink { 798 // There may not be stubbed wallet links following an unstubbed wallet links (for a given network). 799 // So that the server can't roll back someone's active wallet address. 800 return cached, cki, SigchainV2StubbedDisallowed{} 801 } 802 m.VLogf(VLog1, "| Skipping over stubbed-out link: %s", link.id) 803 continue 804 } 805 806 tcl, w := NewTypedChainLink(link) 807 if w != nil { 808 w.Warn(m.G()) 809 } 810 811 m.VLogf(VLog1, "| Verify link: %s %v %v", link.id, link.chainVerified, link.hashVerified) 812 if first { 813 if err = ckf.InsertEldestLink(tcl, un); err != nil { 814 return cached, cki, err 815 } 816 first = false 817 } 818 819 // Optimization: only check sigs on some links, like the final 820 // link, or those that delegate and revoke keys. 821 // Note that we do this *before* processing revocations in the key 822 // family. That's important because a chain link might revoke the same 823 // key that signed it. 824 isDelegating := (tcl.GetRole() != DLGNone) 825 isModifyingKeys := isDelegating || tcl.Type() == string(DelegationTypePGPUpdate) 826 isFinalLink := (linkIndex == len(links)-1) 827 hasRevocations := link.HasRevocations() 828 m.VLogf(VLog1, "| isDelegating: %v, isModifyingKeys: %v, isFinalLink: %v, hasRevocations: %v", 829 isDelegating, isModifyingKeys, isFinalLink, hasRevocations) 830 831 if pgpcl, ok := tcl.(*PGPUpdateChainLink); ok { 832 if hash := pgpcl.GetPGPFullHash(); hash != "" { 833 m.Debug("| Setting active PGP hash for %s: %s", pgpcl.kid, hash) 834 ckf.SetActivePGPHash(pgpcl.kid, hash) 835 } 836 } 837 838 if isModifyingKeys || isFinalLink || hasRevocations { 839 err = link.VerifySigWithKeyFamily(ckf) 840 if err != nil { 841 m.Debug("| Failure in VerifySigWithKeyFamily: %s", err) 842 return cached, cki, err 843 } 844 } 845 846 if isDelegating { 847 err = ckf.Delegate(tcl) 848 if err != nil { 849 m.Debug("| Failure in Delegate: %s", err) 850 return cached, cki, err 851 } 852 } 853 854 if pukl, ok := tcl.(*PerUserKeyChainLink); ok { 855 err := ckf.cki.DelegatePerUserKey(pukl.ToPerUserKey()) 856 if err != nil { 857 return cached, cki, err 858 } 859 } 860 861 if _, ok := tcl.(*WalletStellarChainLink); ok { 862 // Assert that wallet chain links are be >= v2. 863 // They must be v2 in order to be stubbable later for privacy. 864 if link.unpacked.sigVersion < KeybaseSignatureV2 { 865 return cached, cki, SigchainV2Required{} 866 } 867 seenInflatedWalletStellarLink = true 868 } 869 870 if err = tcl.VerifyReverseSig(ckf); err != nil { 871 m.Debug("| Failure in VerifyReverseSig: %s", err) 872 return cached, cki, err 873 } 874 875 if err = ckf.Revoke(tcl); err != nil { 876 return cached, cki, err 877 } 878 879 if err = ckf.UpdateDevices(tcl); err != nil { 880 return cached, cki, err 881 } 882 } 883 884 last.PutSigCheckCache(cki) 885 return cached, cki, err 886 } 887 888 func (sc *SigChain) verifySigsAndComputeKeysCurrent(m MetaContext, eldest keybase1.KID, ckf *ComputedKeyFamily, uid keybase1.UID) (cached bool, linksConsumed int, err error) { 889 890 cached = false 891 m.Debug("+ verifySigsAndComputeKeysCurrent for user %s (eldest = %s)", sc.uid, eldest) 892 defer func() { 893 m.Debug("- verifySigsAndComputeKeysCurrent for user %s -> %s", sc.uid, ErrToOk(err)) 894 }() 895 896 if err = sc.VerifyChain(m, uid); err != nil { 897 return cached, 0, err 898 } 899 900 // AllKeys mode is now the default. 901 if first := sc.getFirstSeqno(); first > keybase1.Seqno(1) { 902 err = ChainLinkWrongSeqnoError{fmt.Sprintf("Wanted a chain from seqno=1, but got seqno=%d", first)} 903 return cached, 0, err 904 } 905 906 // There are 3 cases that we have to think about here for recording the 907 // start of the current subchain (and a fourth where we don't make it here 908 // at all, when the chain is fully cached and fresh): 909 // 910 // 1. The chain is totally empty, because the user is new. 911 // 2. The chain has links, but the user just did a reset, and so the 912 // current subchain is empty. 913 // 3. The common case: a user with some links in the current subchain. 914 // 915 // In cases 1 and 2 we say the subchain start is zero, an invalid seqno. 916 // Write that out now, to overwrite anything we computed during local 917 // sigchain loading. 918 sc.currentSubchainStart = 0 919 920 if ckf.kf == nil || eldest.IsNil() { 921 m.Debug("| VerifyWithKey short-circuit, since no Key available") 922 sc.localCki = NewComputedKeyInfos(sc.G()) 923 ckf.cki = sc.localCki 924 return cached, 0, err 925 } 926 927 links, err := cropToRightmostSubchain(m, sc.chainLinks, eldest, sc.uid) 928 if err != nil { 929 return cached, 0, err 930 } 931 932 // Update the subchain start if we're in case 3 from above. 933 if len(links) > 0 { 934 sc.currentSubchainStart = links[0].GetSeqno() 935 } 936 937 if len(links) == 0 { 938 m.Debug("| Empty chain after we limited to eldest %s", eldest) 939 eldestKey, _ := ckf.FindKeyWithKIDUnsafe(eldest) 940 sc.localCki = NewComputedKeyInfos(sc.G()) 941 err = sc.localCki.InsertServerEldestKey(eldestKey, sc.username) 942 ckf.cki = sc.localCki 943 return cached, 0, err 944 } 945 946 if cached, ckf.cki, err = verifySubchain(m, sc.username, *ckf.kf, links); err != nil { 947 return cached, len(links), err 948 } 949 950 // We used to check for a self-signature of one's keybase username 951 // here, but that doesn't make sense because we haven't accounted 952 // for revocations. We'll go it later, after reconstructing 953 // the id_table. See LoadUser in user.go and 954 // https://github.com/keybase/go/issues/43 955 956 return cached, len(links), nil 957 } 958 959 func reverseListOfChainLinks(arr []ChainLinks) { 960 for i, j := 0, len(arr)-1; i < j; i, j = i+1, j-1 { 961 arr[i], arr[j] = arr[j], arr[i] 962 } 963 } 964 965 func (c ChainLinks) omittingNRightmostLinks(n int) ChainLinks { 966 return c[0 : len(c)-n] 967 } 968 969 // VerifySigsAndComputeKeys iterates over all potentially all incarnations of the user, trying to compute 970 // multiple subchains. It returns (bool, error), where bool is true if the load hit the cache, and false otherwise. 971 func (sc *SigChain) VerifySigsAndComputeKeys(m MetaContext, eldest keybase1.KID, ckf *ComputedKeyFamily, uid keybase1.UID) (bool, error) { 972 // First consume the currently active sigchain. 973 cached, numLinksConsumed, err := sc.verifySigsAndComputeKeysCurrent(m, eldest, ckf, uid) 974 if err != nil || ckf.kf == nil { 975 return cached, err 976 } 977 978 allCached := cached 979 980 // Now let's examine any historical subchains, if there are any. 981 historicalLinks := sc.chainLinks.omittingNRightmostLinks(numLinksConsumed) 982 983 if len(historicalLinks) > 0 { 984 m.Debug("After consuming %d links, there are %d historical links left", 985 numLinksConsumed, len(historicalLinks)) 986 // ignore error here, since it shouldn't kill the overall load if historical subchains don't run 987 // correctly. 988 cached, prevSubchains, _ := verifySigsAndComputeKeysHistorical(m, sc.uid, sc.username, historicalLinks, *ckf.kf) 989 sc.prevSubchains = prevSubchains 990 if !cached { 991 allCached = false 992 } 993 } 994 995 return allCached, nil 996 } 997 998 func verifySigsAndComputeKeysHistorical(m MetaContext, uid keybase1.UID, username NormalizedUsername, allLinks ChainLinks, kf KeyFamily) (allCached bool, prevSubchains []ChainLinks, err error) { 999 1000 defer m.Trace("verifySigsAndComputeKeysHistorical", &err)() 1001 var cached bool 1002 1003 for { 1004 if len(allLinks) == 0 { 1005 m.Debug("Ending iteration through previous subchains; no further links") 1006 break 1007 } 1008 1009 i := len(allLinks) - 1 1010 link := allLinks[i] 1011 eldest := link.ToEldestKID() 1012 seqno := link.GetSeqno() 1013 1014 if eldest.IsNil() { 1015 m.Debug("Ending iteration through previous subchains; saw a nil eldest (@%d)", seqno) 1016 break 1017 } 1018 m.Debug("Examining subchain that ends at %d with eldest %s", seqno, eldest) 1019 1020 var links ChainLinks 1021 links, err = cropToRightmostSubchain(m, allLinks, eldest, uid) 1022 if err != nil { 1023 m.Info("Error backtracking all links from %d: %s", seqno, err) 1024 break 1025 } 1026 1027 cached, _, err = verifySubchain(m, username, kf, links) 1028 if err != nil { 1029 m.Info("Error verifying subchain from %d: %s", seqno, err) 1030 break 1031 } 1032 if !cached { 1033 allCached = false 1034 } 1035 prevSubchains = append(prevSubchains, links) 1036 allLinks = allLinks.omittingNRightmostLinks(len(links)) 1037 } 1038 reverseListOfChainLinks(prevSubchains) 1039 m.Debug("Loaded %d additional historical subchains", len(prevSubchains)) 1040 return allCached, prevSubchains, nil 1041 } 1042 1043 func (sc *SigChain) GetLinkFromSeqno(seqno keybase1.Seqno) *ChainLink { 1044 for _, link := range sc.chainLinks { 1045 if link.GetSeqno() == seqno { 1046 return link 1047 } 1048 } 1049 return nil 1050 } 1051 1052 func (sc *SigChain) GetLinkFromSigID(id keybase1.SigID) *ChainLink { 1053 for _, link := range sc.chainLinks { 1054 if len(link.GetSigID()) == 0 { 1055 // sigID might not be set for stubbed links on other users. If you're looking 1056 // for a specific link by sigID of another user (e.g. for web-of-trust), then 1057 // an intermediate stubbed link might otherwise cause a panic if it's not skipped. 1058 continue 1059 } 1060 if link.GetSigID().Eq(id) { 1061 return link 1062 } 1063 } 1064 return nil 1065 } 1066 1067 // GetLinkFromSigIDQuery will return true if it finds a ChainLink 1068 // with a SigID that starts with query. 1069 func (sc *SigChain) GetLinkFromSigIDQuery(query string) *ChainLink { 1070 for _, link := range sc.chainLinks { 1071 if link.GetSigID().PrefixMatch(query, false) { 1072 return link 1073 } 1074 } 1075 return nil 1076 } 1077 1078 // ======================================================================== 1079 1080 type ChainType struct { 1081 DbType ObjType 1082 Private bool 1083 Encrypted bool 1084 GetMerkleTriple func(u *MerkleUserLeaf) *MerkleTriple 1085 } 1086 1087 var PublicChain = &ChainType{ 1088 DbType: DBSigChainTailPublic, 1089 Private: false, 1090 Encrypted: false, 1091 GetMerkleTriple: func(u *MerkleUserLeaf) *MerkleTriple { return u.public }, 1092 } 1093 1094 // ======================================================================== 1095 1096 type BaseSigChainLoader interface { 1097 Load() (ret *BaseSigChain, err error) 1098 LoadFromServer() (err error) 1099 VerifySigsAndComputeKeys() (err error) 1100 } 1101 type SigChainLoader struct { 1102 MetaContextified 1103 user *User 1104 self bool 1105 leaf *MerkleUserLeaf 1106 chain *SigChain 1107 chainType *ChainType 1108 links ChainLinks 1109 ckf ComputedKeyFamily 1110 dirtyTail *MerkleTriple 1111 currentSubchainStart keybase1.Seqno 1112 stubMode StubMode 1113 1114 // The preloaded sigchain; maybe we're loading a user that already was 1115 // loaded, and here's the existing sigchain. 1116 preload *SigChain 1117 1118 // links that arg getting unstubbed in this load need to match the given linkIDs 1119 unstubs map[keybase1.Seqno]LinkID 1120 } 1121 1122 // ======================================================================== 1123 1124 func (l *SigChainLoader) LoadLastLinkIDFromStorage() (mt *MerkleTriple, err error) { 1125 var tmp MerkleTriple 1126 var found bool 1127 found, err = l.G().LocalDb.GetInto(&tmp, l.dbKey()) 1128 if err != nil { 1129 l.G().Log.Debug("| Error loading last link: %s", err) 1130 } else if !found { 1131 l.G().Log.Debug("| LastLinkId was null") 1132 } else { 1133 mt = &tmp 1134 } 1135 return 1136 } 1137 1138 func (l *SigChainLoader) AccessPreload() bool { 1139 if l.preload == nil { 1140 l.G().Log.Debug("| Preload not provided") 1141 return false 1142 } 1143 l.G().Log.Debug("| Preload successful") 1144 src := l.preload.chainLinks 1145 l.links = make(ChainLinks, len(src)) 1146 copy(l.links, src) 1147 return true 1148 } 1149 1150 func (l *SigChainLoader) LoadLinksFromStorage() (err error) { 1151 uid := l.user.GetUID() 1152 defer l.M().Trace(fmt.Sprintf("SigChainLoader.LoadFromStorage(%s)", uid), 1153 &err)() 1154 var mt *MerkleTriple 1155 1156 if mt, err = l.LoadLastLinkIDFromStorage(); err != nil || mt == nil || mt.LinkID == nil { 1157 l.M().Debug("| short-circuting LoadLinksFromStorage: LoadLastLinkIDFromStorage returned err=%v", err) 1158 if mt == nil { 1159 l.M().Debug("| mt (MerkleTriple) nil result from load last link ID from storage") 1160 } 1161 if mt != nil && mt.LinkID == nil { 1162 l.M().Debug("| mt (MerkleTriple) from storage has a nil link ID") 1163 } 1164 return err 1165 } 1166 1167 currentLink, err := ImportLinkFromStorage(l.M(), mt.LinkID, l.selfUID()) 1168 if err != nil { 1169 return err 1170 } 1171 if currentLink == nil { 1172 l.M().Debug("tried to load previous link ID %s, but link not found", mt.LinkID.String()) 1173 return nil 1174 } 1175 links := ChainLinks{currentLink} 1176 1177 // Load all the links we have locally, and record the start of the current 1178 // subchain as we go. We might find out later when we check freshness that 1179 // a reset has happened, so this result only gets used if the local chain 1180 // turns out to be fresh. 1181 for { 1182 select { 1183 case <-l.M().Ctx().Done(): 1184 return l.M().Ctx().Err() 1185 default: 1186 } 1187 1188 if currentLink.GetSeqno() == 1 { 1189 if l.currentSubchainStart == 0 { 1190 l.currentSubchainStart = 1 1191 } 1192 break 1193 } 1194 prevLink, err := ImportLinkFromStorage(l.M(), currentLink.GetPrev(), l.selfUID()) 1195 if err != nil { 1196 return err 1197 } 1198 if prevLink == nil { 1199 l.M().Debug("tried to load previous link ID %s, but link not found", currentLink.GetPrev()) 1200 return nil 1201 } 1202 1203 links = append(links, prevLink) 1204 if l.currentSubchainStart == 0 { 1205 isStart, err := isSubchainStart(l.M(), currentLink, prevLink, uid) 1206 if err != nil { 1207 return err 1208 } 1209 if isStart { 1210 l.currentSubchainStart = currentLink.GetSeqno() 1211 } 1212 } 1213 currentLink = prevLink 1214 } 1215 1216 reverse(links) 1217 l.M().Debug("| Loaded %d links", len(links)) 1218 1219 // Set the links field in the loader object. We're going to mutate this field just below, 1220 // in the next step of loading. 1221 l.links = links 1222 1223 // Now that we've set the links array above, we're going to potentially discard the stubbed links, 1224 // and then set a mapping of (seqno -> linkID) so that the server doesn't lie on an unstubbing. 1225 l.maybeDiscardStubbedLinks() 1226 1227 return 1228 } 1229 1230 // maybeDiscardStubbedLinks will look at the sigchain links loaded from the DB and will maybe throw 1231 // some away on the basis of (a) if we're in StubModeUnstubbed load mode (meaning we don't want any stubs); 1232 // and (b) there are some stubs found. But it won't totally throw the stubs away; instead, it will put them 1233 // in map to check that server eventually unstubs the right values (by mapping Seqno -> LinkID). 1234 func (l *SigChainLoader) maybeDiscardStubbedLinks() { 1235 1236 if l.stubMode == StubModeStubbed { 1237 return 1238 } 1239 1240 firstStubbedLink := -1 1241 for i, link := range l.links { 1242 if link.IsStubbed() { 1243 firstStubbedLink = i 1244 l.M().Debug("| Breaking at first stub, which we'll overwrite: %s", link.id) 1245 break 1246 } 1247 } 1248 1249 if firstStubbedLink < 0 { 1250 l.M().Debug("| want an unstubbed load, but all links unstubbed, so nothing to do") 1251 return 1252 } 1253 1254 // Keep track of all links that we're going to unstub; we're going to require that 1255 // the server sends down linkIDs as we previously wrote down to storage. 1256 l.unstubs = make(map[keybase1.Seqno]LinkID) 1257 for _, link := range l.links[firstStubbedLink:] { 1258 l.unstubs[link.GetSeqno()] = link.id 1259 } 1260 1261 // The only links we're leaving are the unstubbed links. 1262 l.links = l.links[0:firstStubbedLink] 1263 } 1264 1265 // ======================================================================== 1266 1267 func (l *SigChainLoader) MakeSigChain() error { 1268 sc := &SigChain{ 1269 uid: l.user.GetUID(), 1270 username: l.user.GetNormalizedName(), 1271 chainLinks: l.links, 1272 currentSubchainStart: l.currentSubchainStart, 1273 Contextified: NewContextified(l.G()), 1274 } 1275 for _, link := range l.links { 1276 link.SetParent(sc) 1277 } 1278 l.chain = sc 1279 return nil 1280 } 1281 1282 // ======================================================================== 1283 1284 func (l *SigChainLoader) GetKeyFamily() (err error) { 1285 l.ckf.kf = l.user.GetKeyFamily() 1286 return 1287 } 1288 1289 // ======================================================================== 1290 1291 func (l *SigChainLoader) GetMerkleTriple() (ret *MerkleTriple) { 1292 if l.leaf != nil { 1293 ret = l.chainType.GetMerkleTriple(l.leaf) 1294 } 1295 return 1296 } 1297 1298 // ======================================================================== 1299 1300 func (sc *SigChain) CheckFreshness(srv *MerkleTriple) (current bool, err error) { 1301 cli := sc.GetCurrentTailTriple() 1302 1303 future := sc.GetFutureChainTail() 1304 Efn := NewServerChainError 1305 sc.G().Log.Debug("+ CheckFreshness") 1306 defer sc.G().Log.Debug("- CheckFreshness (%s) -> (%v,%s)", sc.uid, current, ErrToOk(err)) 1307 a := keybase1.Seqno(-1) 1308 b := keybase1.Seqno(-1) 1309 1310 if srv != nil { 1311 sc.G().Log.Debug("| Server triple: %v", srv) 1312 b = srv.Seqno 1313 } else { 1314 sc.G().Log.Debug("| Server triple=nil") 1315 } 1316 if cli != nil { 1317 sc.G().Log.Debug("| Client triple: %v", cli) 1318 a = cli.Seqno 1319 } else { 1320 sc.G().Log.Debug("| Client triple=nil") 1321 } 1322 if future != nil { 1323 sc.G().Log.Debug("| Future triple: %v", future) 1324 } else { 1325 sc.G().Log.Debug("| Future triple=nil") 1326 } 1327 1328 if srv == nil && cli != nil { 1329 err = Efn("Server claimed not to have this user in its tree (we had v=%d)", cli.Seqno) 1330 return 1331 } 1332 1333 if srv == nil { 1334 return 1335 } 1336 1337 if b < 0 || a > b { 1338 err = Efn("Server version-rollback suspected: Local %d > %d", a, b) 1339 return 1340 } 1341 1342 if b == a { 1343 sc.G().Log.Debug("| Local chain version is up-to-date @ version %d", b) 1344 current = true 1345 if cli == nil { 1346 err = Efn("Failed to read last link for user") 1347 return 1348 } 1349 if !cli.LinkID.Eq(srv.LinkID) { 1350 err = Efn("The server returned the wrong sigchain tail") 1351 return 1352 } 1353 } else { 1354 sc.G().Log.Debug("| Local chain version is out-of-date: %d < %d", a, b) 1355 current = false 1356 } 1357 1358 if current && future != nil && (cli == nil || cli.Seqno < future.Seqno) { 1359 sc.G().Log.Debug("| Still need to reload, since locally, we know seqno=%d is last", future.Seqno) 1360 current = false 1361 } 1362 1363 return 1364 } 1365 1366 // ======================================================================== 1367 1368 func (l *SigChainLoader) CheckFreshness() (current bool, err error) { 1369 return l.chain.CheckFreshness(l.GetMerkleTriple()) 1370 } 1371 1372 // ======================================================================== 1373 1374 func (sc *SigChain) HasStubs() bool { 1375 for _, link := range sc.chainLinks { 1376 if link.IsStubbed() { 1377 return true 1378 } 1379 } 1380 return len(sc.chainLinks) != 0 1381 } 1382 1383 // ======================================================================== 1384 1385 func (l *SigChainLoader) HasStubs() bool { 1386 return l.chain.HasStubs() 1387 } 1388 1389 // ======================================================================== 1390 1391 func (l *SigChainLoader) selfUID() (uid keybase1.UID) { 1392 if !l.self { 1393 return 1394 } 1395 return l.user.GetUID() 1396 } 1397 1398 // ======================================================================== 1399 1400 func (l *SigChainLoader) LoadFromServer() (err error) { 1401 srv := l.GetMerkleTriple() 1402 1403 l.dirtyTail, err = l.chain.LoadFromServer(l.M(), srv, l.selfUID(), l.stubMode, l.unstubs) 1404 1405 if err != nil { 1406 return err 1407 } 1408 return nil 1409 } 1410 1411 // ======================================================================== 1412 1413 func (l *SigChainLoader) VerifySigsAndComputeKeys() (err error) { 1414 l.M().Debug("VerifySigsAndComputeKeys(): l.leaf: %v, l.leaf.eldest: %v, l.ckf: %v", l.leaf, l.leaf.eldest, l.ckf) 1415 if l.ckf.kf == nil { 1416 return nil 1417 } 1418 1419 uid := l.user.GetUID() 1420 _, err = l.chain.VerifySigsAndComputeKeys(l.M(), l.leaf.eldest, &l.ckf, uid) 1421 if err != nil { 1422 return err 1423 } 1424 1425 // TODO: replay older sigchains if the flag specifies to do so. 1426 return nil 1427 } 1428 1429 func (l *SigChainLoader) dbKey() DbKey { 1430 return DbKeyUID(l.chainType.DbType, l.user.GetUID()) 1431 } 1432 1433 func (l *SigChainLoader) StoreTail() (err error) { 1434 if l.dirtyTail == nil { 1435 return nil 1436 } 1437 err = l.G().LocalDb.PutObj(l.dbKey(), nil, l.dirtyTail) 1438 l.M().Debug("| Storing dirtyTail @ %d (%v)", l.dirtyTail.Seqno, l.dirtyTail) 1439 if err == nil { 1440 l.dirtyTail = nil 1441 } 1442 return 1443 } 1444 1445 // Store a SigChain to local storage as a result of having loaded it. 1446 // We eagerly write loaded chain links to storage if they verify properly. 1447 func (l *SigChainLoader) Store() (err error) { 1448 err = l.StoreTail() 1449 if err == nil { 1450 err = l.chain.Store(l.M()) 1451 } 1452 return 1453 } 1454 1455 func (l *SigChainLoader) merkleTreeEldestMatchesLastLinkEldest() bool { 1456 lastLink := l.chain.GetLastLink() 1457 if lastLink == nil { 1458 return false 1459 } 1460 return lastLink.ToEldestKID().Equal(l.leaf.eldest) 1461 } 1462 1463 // Load is the main entry point into the SigChain loader. It runs through 1464 // all of the steps to load a chain in from storage, to refresh it against 1465 // the server, and to verify its integrity. 1466 func (l *SigChainLoader) Load() (ret *SigChain, err error) { 1467 defer TimeLog(fmt.Sprintf("SigChainLoader#Load: %s", l.user.GetName()), l.G().Clock().Now(), l.G().Log.Debug) 1468 var current bool 1469 var preload bool 1470 1471 uid := l.user.GetUID() 1472 1473 l.M().Debug("+ SigChainLoader#Load(%s)", uid) 1474 defer func() { 1475 l.M().Debug("- SigChainLoader#Load(%s) -> (%v, %s)", uid, (ret != nil), ErrToOk(err)) 1476 }() 1477 1478 stage := func(s string) { 1479 l.M().Debug("| SigChainLoader#Load(%s) %s", uid, s) 1480 } 1481 1482 stage("GetFingerprint") 1483 if err = l.GetKeyFamily(); err != nil { 1484 return nil, err 1485 } 1486 1487 stage("AccessPreload") 1488 preload = l.AccessPreload() 1489 1490 if !preload { 1491 stage("LoadLinksFromStorage") 1492 if err = l.LoadLinksFromStorage(); err != nil { 1493 return nil, err 1494 } 1495 } 1496 1497 stage("MakeSigChain") 1498 if err = l.MakeSigChain(); err != nil { 1499 return nil, err 1500 } 1501 ret = l.chain 1502 stage("VerifyChain") 1503 if err = l.chain.VerifyChain(l.M(), uid); err != nil { 1504 return nil, err 1505 } 1506 stage("CheckFreshness") 1507 if current, err = l.CheckFreshness(); err != nil { 1508 return nil, err 1509 } 1510 if !current { 1511 stage("LoadFromServer") 1512 if err = l.LoadFromServer(); err != nil { 1513 return nil, err 1514 } 1515 } else if l.chain.GetComputedKeyInfosWithVersionBust() == nil { 1516 // The chain tip doesn't have a cached cki, probably because new 1517 // signatures have shown up since the last time we loaded it. 1518 l.M().Debug("| Need to reverify chain since we don't have ComputedKeyInfos") 1519 } else if !l.merkleTreeEldestMatchesLastLinkEldest() { 1520 // CheckFreshness above might've decided our chain tip hasn't moved, 1521 // but we might still need to proceed with the rest of the load if the 1522 // eldest KID has changed. 1523 l.M().Debug("| Merkle leaf doesn't match the chain tip.") 1524 } else { 1525 // The chain tip has a cached cki, AND the current eldest kid matches 1526 // it. Use what's cached and short circuit. 1527 l.M().Debug("| Sigchain was fully cached. Short-circuiting verification.") 1528 ret.wasFullyCached = true 1529 stage("VerifySig (in fully cached)") 1530 1531 // Even though we're fully cached, we still need to call the below, so 1532 // we recompute historical subchains. Otherwise, we might hose our 1533 // UPAK caches. 1534 if err = l.VerifySigsAndComputeKeys(); err != nil { 1535 return nil, err 1536 } 1537 1538 // Success in the fully cached case. 1539 return ret, nil 1540 } 1541 1542 stage("VerifyChain") 1543 if err = l.chain.VerifyChain(l.M(), uid); err != nil { 1544 return nil, err 1545 } 1546 1547 stage("StoreChain") 1548 if err = l.chain.Store(l.M()); err != nil { 1549 l.M().Debug("| continuing past error storing chain links: %s", err) 1550 } 1551 stage("VerifySig") 1552 if err = l.VerifySigsAndComputeKeys(); err != nil { 1553 return nil, err 1554 } 1555 stage("Store") 1556 if err = l.Store(); err != nil { 1557 l.M().Debug("| continuing past error storing chain: %s", err) 1558 } 1559 1560 return ret, nil 1561 }