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  }