diff options
Diffstat (limited to 'sth.go')
| -rw-r--r-- | sth.go | 143 | 
1 files changed, 0 insertions, 143 deletions
@@ -1,143 +0,0 @@ -package stfe - -import ( -	"context" -	"crypto/ed25519" -	"fmt" -	"reflect" -	"sync" - -	"github.com/golang/glog" -	"github.com/google/certificate-transparency-go/schedule" -	"github.com/google/trillian" -	ttypes "github.com/google/trillian/types" -	"github.com/system-transparency/stfe/types" -) - -// SthSource provides access to the log's (co)signed tree heads -type SthSource interface { -	Latest(context.Context) (*types.SignedTreeHead, error) -	Stable(context.Context) (*types.SignedTreeHead, error) -	Cosigned(context.Context) (*types.SignedTreeHead, error) -	AddCosignature(context.Context, ed25519.PublicKey, *[types.SignatureSize]byte) error -	Run(context.Context) -} - -// ActiveSthSource implements the SthSource interface for an STFE instance that -// accepts new logging requests, i.e., the log is running in read+write mode. -type ActiveSthSource struct { -	client        trillian.TrillianLogClient -	logParameters *LogParameters -	sync.RWMutex - -	// cosigned is the current cosigned tree head that is served -	cosigned types.SignedTreeHead - -	// tosign is the current tree head that is being cosigned -	tosign types.SignedTreeHead - -	// cosignature keeps track of all collected cosignatures for tosign -	cosignature map[[types.HashSize]byte]*types.SigIdent -} - -func NewActiveSthSource(cli trillian.TrillianLogClient, lp *LogParameters) (*ActiveSthSource, error) { -	s := ActiveSthSource{ -		client:        cli, -		logParameters: lp, -	} - -	ctx, _ := context.WithTimeout(context.Background(), lp.Deadline) -	sth, err := s.Latest(ctx) -	if err != nil { -		return nil, fmt.Errorf("Latest: %v", err) -	} - -	s.cosigned = *sth -	s.tosign = *sth -	s.cosignature = make(map[[types.HashSize]byte]*types.SigIdent) -	return &s, nil -} - -func (s *ActiveSthSource) Run(ctx context.Context) { -	schedule.Every(ctx, s.logParameters.Interval, func(ctx context.Context) { -		// get the next stable sth -		ictx, _ := context.WithTimeout(ctx, s.logParameters.Deadline) -		sth, err := s.Latest(ictx) -		if err != nil { -			glog.Warningf("cannot rotate without new sth: Latest: %v", err) -			return -		} -		// rotate -		s.Lock() -		defer s.Unlock() -		s.rotate(sth) -	}) -} - -func (s *ActiveSthSource) Latest(ctx context.Context) (*types.SignedTreeHead, error) { -	trsp, err := s.client.GetLatestSignedLogRoot(ctx, &trillian.GetLatestSignedLogRootRequest{ -		LogId: s.logParameters.TreeId, -	}) -	var lr ttypes.LogRootV1 -	if errInner := checkGetLatestSignedLogRoot(s.logParameters, trsp, err, &lr); errInner != nil { -		return nil, fmt.Errorf("invalid signed log root response: %v", errInner) -	} -	return s.logParameters.Sign(NewTreeHeadFromLogRoot(&lr)) -} - -func (s *ActiveSthSource) Stable(_ context.Context) (*types.SignedTreeHead, error) { -	s.RLock() -	defer s.RUnlock() -	return &s.tosign, nil -} - -func (s *ActiveSthSource) Cosigned(_ context.Context) (*types.SignedTreeHead, error) { -	s.RLock() -	defer s.RUnlock() -	return &s.cosigned, nil -} - -func (s *ActiveSthSource) AddCosignature(_ context.Context, vk ed25519.PublicKey, sig *[types.SignatureSize]byte) error { -	s.Lock() -	defer s.Unlock() - -	if msg := s.tosign.TreeHead.Marshal(); !ed25519.Verify(vk, msg, sig[:]) { -		return fmt.Errorf("Invalid signature for tree head with timestamp: %d", s.tosign.TreeHead.Timestamp) -	} -	witness := types.Hash(vk[:]) -	if _, ok := s.cosignature[*witness]; ok { -		glog.V(3).Infof("received cosignature again (duplicate)") -		return nil // duplicate -	} -	s.cosignature[*witness] = &types.SigIdent{ -		Signature: sig, -		KeyHash:   witness, -	} -	glog.V(3).Infof("accepted new cosignature") -	return nil -} - -// rotate rotates the log's cosigned and stable STH.  The caller must aquire the -// source's read-write lock if there are concurrent reads and/or writes. -func (s *ActiveSthSource) rotate(next *types.SignedTreeHead) { -	if reflect.DeepEqual(s.cosigned.TreeHead, s.tosign.TreeHead) { -		for _, sigident := range s.cosigned.SigIdent[1:] { // skip log sigident -			if _, ok := s.cosignature[*sigident.KeyHash]; !ok { -				s.cosignature[*sigident.KeyHash] = sigident -			} -		} -	} -	var cosignatures []*types.SigIdent -	for _, sigident := range s.cosignature { -		cosignatures = append(cosignatures, sigident) -	} // cosignatures contains all cosignatures, even if repeated tree head - -	// Update cosigned tree head -	s.cosigned.TreeHead = s.tosign.TreeHead -	s.cosigned.SigIdent = append(s.tosign.SigIdent, cosignatures...) - -	// Update to-sign tree head -	s.tosign = *next -	s.cosignature = make(map[[types.HashSize]byte]*types.SigIdent) -	glog.V(3).Infof("rotated sth") -}  | 
