...

Source file src/github.com/theupdateframework/go-tuf/repo_test.go

Documentation: github.com/theupdateframework/go-tuf

     1  package tuf
     2  
     3  import (
     4  	"bytes"
     5  	"crypto"
     6  	"crypto/elliptic"
     7  	"crypto/rand"
     8  	"encoding/hex"
     9  	"encoding/json"
    10  	"errors"
    11  	"fmt"
    12  	"log"
    13  	"os"
    14  	"path"
    15  	"path/filepath"
    16  	"reflect"
    17  	"sort"
    18  	"strings"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/secure-systems-lab/go-securesystemslib/cjson"
    23  	"github.com/secure-systems-lab/go-securesystemslib/encrypted"
    24  	"github.com/theupdateframework/go-tuf/data"
    25  	"github.com/theupdateframework/go-tuf/internal/sets"
    26  	"github.com/theupdateframework/go-tuf/pkg/keys"
    27  	"github.com/theupdateframework/go-tuf/pkg/targets"
    28  	"github.com/theupdateframework/go-tuf/util"
    29  	"github.com/theupdateframework/go-tuf/verify"
    30  	"golang.org/x/crypto/ed25519"
    31  	. "gopkg.in/check.v1"
    32  )
    33  
    34  // Hook up gocheck into the "go test" runner.
    35  func Test(t *testing.T) { TestingT(t) }
    36  
    37  type RepoSuite struct{}
    38  
    39  var _ = Suite(&RepoSuite{})
    40  
    41  func (RepoSuite) TestNewRepo(c *C) {
    42  	testNewRepo(c, NewRepo)
    43  }
    44  
    45  func (RepoSuite) TestNewRepoIndent(c *C) {
    46  	testNewRepo(c, func(local LocalStore, hashAlgorithms ...string) (*Repo, error) {
    47  		return NewRepoIndent(local, "", "\t")
    48  	})
    49  }
    50  
    51  // UniqueKeys returns the unique keys for each associated role.
    52  // We might have multiple key IDs that correspond to the same key.
    53  func UniqueKeys(r *data.Root) map[string][]*data.PublicKey {
    54  	keysByRole := make(map[string][]*data.PublicKey)
    55  	for name, role := range r.Roles {
    56  		seen := make(map[string]struct{})
    57  		roleKeys := []*data.PublicKey{}
    58  		for _, id := range role.KeyIDs {
    59  			// Double-check that there is actually a key with that ID.
    60  			if key, ok := r.Keys[id]; ok {
    61  				verifier, err := keys.GetVerifier(key)
    62  				if err != nil {
    63  					continue
    64  				}
    65  				val := verifier.Public()
    66  				if _, ok := seen[val]; ok {
    67  					continue
    68  				}
    69  				seen[val] = struct{}{}
    70  				roleKeys = append(roleKeys, key)
    71  			}
    72  		}
    73  		keysByRole[name] = roleKeys
    74  	}
    75  	return keysByRole
    76  }
    77  
    78  // AssertNumUniqueKeys verifies that the number of unique root keys for a given role is as expected.
    79  func (*RepoSuite) assertNumUniqueKeys(c *C, root *data.Root, role string, num int) {
    80  	c.Assert(UniqueKeys(root)[role], HasLen, num)
    81  }
    82  
    83  func testNewRepo(c *C, newRepo func(local LocalStore, hashAlgorithms ...string) (*Repo, error)) {
    84  	meta := map[string]json.RawMessage{
    85  		"root.json": []byte(`{
    86  		  "signed": {
    87  		    "_type": "root",
    88  		    "version": 1,
    89  		    "expires": "2015-12-26T03:26:55.821520874Z",
    90  		    "keys": {},
    91  		    "roles": {}
    92  		  },
    93  		  "signatures": []
    94  		}`),
    95  		"targets.json": []byte(`{
    96  		  "signed": {
    97  		    "_type": "targets",
    98  		    "version": 1,
    99  		    "expires": "2015-03-26T03:26:55.82155686Z",
   100  		    "targets": {}
   101  		  },
   102  		  "signatures": []
   103  		}`),
   104  		"snapshot.json": []byte(`{
   105  		  "signed": {
   106  		    "_type": "snapshot",
   107  		    "version": 1,
   108  		    "expires": "2015-01-02T03:26:55.821585981Z",
   109  		    "meta": {}
   110  		  },
   111  		  "signatures": []
   112  		}`),
   113  		"timestamp.json": []byte(`{
   114  		  "signed": {
   115  		    "_type": "timestamp",
   116  		    "version": 1,
   117  		    "expires": "2014-12-27T03:26:55.821599702Z",
   118  		    "meta": {}
   119  		  },
   120  		  "signatures": []
   121  		}`),
   122  	}
   123  	local := MemoryStore(meta, nil)
   124  	r, err := newRepo(local)
   125  	c.Assert(err, IsNil)
   126  
   127  	root, err := r.root()
   128  	c.Assert(err, IsNil)
   129  	c.Assert(root.Type, Equals, "root")
   130  	c.Assert(root.Version, Equals, int64(1))
   131  	c.Assert(root.Keys, NotNil)
   132  	c.Assert(root.Keys, HasLen, 0)
   133  
   134  	targets, err := r.topLevelTargets()
   135  	c.Assert(err, IsNil)
   136  	c.Assert(targets.Type, Equals, "targets")
   137  	c.Assert(targets.Version, Equals, int64(1))
   138  	c.Assert(targets.Targets, NotNil)
   139  	c.Assert(targets.Targets, HasLen, 0)
   140  
   141  	snapshot, err := r.snapshot()
   142  	c.Assert(err, IsNil)
   143  	c.Assert(snapshot.Type, Equals, "snapshot")
   144  	c.Assert(snapshot.Version, Equals, int64(1))
   145  	c.Assert(snapshot.Meta, NotNil)
   146  	c.Assert(snapshot.Meta, HasLen, 0)
   147  
   148  	timestamp, err := r.timestamp()
   149  	c.Assert(err, IsNil)
   150  	c.Assert(timestamp.Type, Equals, "timestamp")
   151  	c.Assert(timestamp.Version, Equals, int64(1))
   152  	c.Assert(timestamp.Meta, NotNil)
   153  	c.Assert(timestamp.Meta, HasLen, 0)
   154  }
   155  
   156  func (rs *RepoSuite) TestInit(c *C) {
   157  	local := MemoryStore(
   158  		make(map[string]json.RawMessage),
   159  		map[string][]byte{"foo.txt": []byte("foo")},
   160  	)
   161  	r, err := NewRepo(local)
   162  	c.Assert(err, IsNil)
   163  
   164  	// Init() sets root.ConsistentSnapshot
   165  	for _, v := range []bool{true, false} {
   166  		c.Assert(r.Init(v), IsNil)
   167  		root, err := r.root()
   168  		c.Assert(err, IsNil)
   169  		c.Assert(root.ConsistentSnapshot, Equals, v)
   170  	}
   171  
   172  	// Add a target.
   173  	generateAndAddPrivateKey(c, r, "targets")
   174  	c.Assert(r.AddTarget("foo.txt", nil), IsNil)
   175  
   176  	// Init() fails if targets have been added
   177  	c.Assert(r.Init(true), Equals, ErrInitNotAllowed)
   178  }
   179  
   180  func genKey(c *C, r *Repo, role string) []string {
   181  	keyids, err := r.GenKey(role)
   182  	c.Assert(err, IsNil)
   183  	c.Assert(len(keyids) > 0, Equals, true)
   184  	return keyids
   185  }
   186  
   187  func (rs *RepoSuite) TestGenKey(c *C) {
   188  	local := MemoryStore(make(map[string]json.RawMessage), nil)
   189  	r, err := NewRepo(local)
   190  	c.Assert(err, IsNil)
   191  
   192  	// generate a key for an unknown role
   193  	_, err = r.GenKey("foo")
   194  	c.Assert(err, Equals, ErrInvalidRole{"foo", "only support adding keys for top-level roles"})
   195  
   196  	// generate a root key
   197  	ids := genKey(c, r, "root")
   198  
   199  	// check root metadata is correct
   200  	root, err := r.root()
   201  	c.Assert(err, IsNil)
   202  	c.Assert(root.Roles, NotNil)
   203  	c.Assert(root.Roles, HasLen, 1)
   204  	rs.assertNumUniqueKeys(c, root, "root", 1)
   205  	rootRole, ok := root.Roles["root"]
   206  	if !ok {
   207  		c.Fatal("missing root role")
   208  	}
   209  	c.Assert(rootRole.KeyIDs, HasLen, 1)
   210  	c.Assert(rootRole.KeyIDs, DeepEquals, ids)
   211  	for _, keyID := range ids {
   212  		k, ok := root.Keys[keyID]
   213  		if !ok {
   214  			c.Fatal("missing key")
   215  		}
   216  		c.Assert(k.IDs(), DeepEquals, ids)
   217  		pk, err := keys.GetVerifier(k)
   218  		c.Assert(err, IsNil)
   219  		c.Assert(pk.Public(), HasLen, ed25519.PublicKeySize)
   220  	}
   221  
   222  	// check root key + role are in db
   223  	db, err := r.topLevelKeysDB()
   224  	c.Assert(err, IsNil)
   225  	for _, keyID := range ids {
   226  		rootKey, err := db.GetVerifier(keyID)
   227  		c.Assert(err, IsNil)
   228  		c.Assert(rootKey.MarshalPublicKey().IDs(), DeepEquals, ids)
   229  		role := db.GetRole("root")
   230  		c.Assert(role.KeyIDs, DeepEquals, sets.StringSliceToSet(ids))
   231  
   232  		// check the key was saved correctly
   233  		localKeys, err := local.GetSigners("root")
   234  		c.Assert(err, IsNil)
   235  		c.Assert(localKeys, HasLen, 1)
   236  		c.Assert(localKeys[0].PublicData().IDs(), DeepEquals, ids)
   237  
   238  		// check RootKeys() is correct
   239  		rootKeys, err := r.RootKeys()
   240  		c.Assert(err, IsNil)
   241  		c.Assert(rootKeys, HasLen, 1)
   242  		c.Assert(rootKeys[0].IDs(), DeepEquals, rootKey.MarshalPublicKey().IDs())
   243  		pk, err := keys.GetVerifier(rootKeys[0])
   244  		c.Assert(err, IsNil)
   245  		c.Assert(pk.Public(), DeepEquals, rootKey.Public())
   246  	}
   247  
   248  	rootKey, err := db.GetVerifier(ids[0])
   249  	c.Assert(err, IsNil)
   250  
   251  	// generate two targets keys
   252  	genKey(c, r, "targets")
   253  	genKey(c, r, "targets")
   254  
   255  	// check root metadata is correct
   256  	root, err = r.root()
   257  	c.Assert(err, IsNil)
   258  	c.Assert(root.Roles, HasLen, 2)
   259  	rs.assertNumUniqueKeys(c, root, "root", 1)
   260  	rs.assertNumUniqueKeys(c, root, "targets", 2)
   261  	targetsRole, ok := root.Roles["targets"]
   262  	if !ok {
   263  		c.Fatal("missing targets role")
   264  	}
   265  	c.Assert(targetsRole.KeyIDs, HasLen, 2)
   266  	targetKeyIDs := make(map[string]struct{}, 2)
   267  	db, err = r.topLevelKeysDB()
   268  	c.Assert(err, IsNil)
   269  	for _, id := range targetsRole.KeyIDs {
   270  		targetKeyIDs[id] = struct{}{}
   271  		_, ok = root.Keys[id]
   272  		if !ok {
   273  			c.Fatal("missing key")
   274  		}
   275  		verifier, err := db.GetVerifier(id)
   276  		c.Assert(err, IsNil)
   277  		c.Assert(verifier.MarshalPublicKey().ContainsID(id), Equals, true)
   278  	}
   279  	role := db.GetRole("targets")
   280  	c.Assert(role.KeyIDs, DeepEquals, targetKeyIDs)
   281  
   282  	// check RootKeys() is unchanged
   283  	rootKeys, err := r.RootKeys()
   284  	c.Assert(err, IsNil)
   285  	c.Assert(rootKeys, HasLen, 1)
   286  	c.Assert(rootKeys[0].IDs(), DeepEquals, rootKey.MarshalPublicKey().IDs())
   287  
   288  	// check the keys were saved correctly
   289  	localKeys, err := local.GetSigners("targets")
   290  	c.Assert(err, IsNil)
   291  	c.Assert(localKeys, HasLen, 2)
   292  	for _, key := range localKeys {
   293  		found := false
   294  		for _, id := range targetsRole.KeyIDs {
   295  			if key.PublicData().ContainsID(id) {
   296  				found = true
   297  				break
   298  			}
   299  		}
   300  		if !found {
   301  			c.Fatal("missing key")
   302  		}
   303  	}
   304  
   305  	// check root.json got staged
   306  	meta, err := local.GetMeta()
   307  	c.Assert(err, IsNil)
   308  	rootJSON, ok := meta["root.json"]
   309  	if !ok {
   310  		c.Fatal("missing root metadata")
   311  	}
   312  	s := &data.Signed{}
   313  	c.Assert(json.Unmarshal(rootJSON, s), IsNil)
   314  	stagedRoot := &data.Root{}
   315  	c.Assert(json.Unmarshal(s.Signed, stagedRoot), IsNil)
   316  	c.Assert(stagedRoot.Type, Equals, root.Type)
   317  	c.Assert(stagedRoot.Version, Equals, root.Version)
   318  	c.Assert(stagedRoot.Expires.UnixNano(), Equals, root.Expires.UnixNano())
   319  
   320  	// make sure both root and stagedRoot have evaluated IDs(), otherwise
   321  	// DeepEquals will fail because those values might not have been
   322  	// computed yet.
   323  	for _, key := range root.Keys {
   324  		key.IDs()
   325  	}
   326  	for _, key := range stagedRoot.Keys {
   327  		key.IDs()
   328  	}
   329  	c.Assert(stagedRoot.Keys, DeepEquals, root.Keys)
   330  	c.Assert(stagedRoot.Roles, DeepEquals, root.Roles)
   331  }
   332  
   333  func addPrivateKey(c *C, r *Repo, role string, key keys.Signer) []string {
   334  	err := r.AddPrivateKey(role, key)
   335  	c.Assert(err, IsNil)
   336  	keyids := key.PublicData().IDs()
   337  	c.Assert(len(keyids) > 0, Equals, true)
   338  	return keyids
   339  }
   340  
   341  func generateAndAddPrivateKey(c *C, r *Repo, role string) []string {
   342  	signer, err := keys.GenerateEd25519Key()
   343  	c.Assert(err, IsNil)
   344  	return addPrivateKey(c, r, role, signer)
   345  }
   346  
   347  func (rs *RepoSuite) TestAddPrivateKey(c *C) {
   348  	local := MemoryStore(make(map[string]json.RawMessage), nil)
   349  	r, err := NewRepo(local)
   350  	c.Assert(err, IsNil)
   351  
   352  	// generate a key for an unknown role
   353  	signer, err := keys.GenerateEd25519Key()
   354  	c.Assert(err, IsNil)
   355  	err = r.AddPrivateKey("foo", signer)
   356  	c.Assert(err, Equals, ErrInvalidRole{"foo", "only support adding keys for top-level roles"})
   357  
   358  	// add a root key
   359  	ids := addPrivateKey(c, r, "root", signer)
   360  
   361  	// check root metadata is correct
   362  	root, err := r.root()
   363  	c.Assert(err, IsNil)
   364  	c.Assert(root.Version, Equals, int64(1))
   365  	c.Assert(root.Roles, NotNil)
   366  	c.Assert(root.Roles, HasLen, 1)
   367  	rs.assertNumUniqueKeys(c, root, "root", 1)
   368  	rootRole, ok := root.Roles["root"]
   369  	if !ok {
   370  		c.Fatal("missing root role")
   371  	}
   372  	c.Assert(rootRole.KeyIDs, HasLen, 1)
   373  	c.Assert(rootRole.KeyIDs, DeepEquals, ids)
   374  	for _, keyID := range ids {
   375  		k, ok := root.Keys[keyID]
   376  		if !ok {
   377  			c.Fatalf("missing key %s", keyID)
   378  		}
   379  		c.Assert(k.IDs(), DeepEquals, ids)
   380  		pk, err := keys.GetVerifier(k)
   381  		c.Assert(err, IsNil)
   382  		c.Assert(pk.Public(), HasLen, ed25519.PublicKeySize)
   383  	}
   384  
   385  	// check root key + role are in db
   386  	db, err := r.topLevelKeysDB()
   387  	c.Assert(err, IsNil)
   388  	for _, keyID := range ids {
   389  		rootKey, err := db.GetVerifier(keyID)
   390  		c.Assert(err, IsNil)
   391  		c.Assert(rootKey.MarshalPublicKey().IDs(), DeepEquals, ids)
   392  		role := db.GetRole("root")
   393  		c.Assert(role.KeyIDs, DeepEquals, sets.StringSliceToSet(ids))
   394  
   395  		// check the key was saved correctly
   396  		localKeys, err := local.GetSigners("root")
   397  		c.Assert(err, IsNil)
   398  		c.Assert(localKeys, HasLen, 1)
   399  		c.Assert(localKeys[0].PublicData().IDs(), DeepEquals, ids)
   400  
   401  		// check RootKeys() is correct
   402  		rootKeys, err := r.RootKeys()
   403  		c.Assert(err, IsNil)
   404  		c.Assert(rootKeys, HasLen, 1)
   405  		c.Assert(rootKeys[0].IDs(), DeepEquals, rootKey.MarshalPublicKey().IDs())
   406  		pk, err := keys.GetVerifier(rootKeys[0])
   407  		c.Assert(err, IsNil)
   408  		c.Assert(pk.Public(), DeepEquals, rootKey.Public())
   409  	}
   410  
   411  	rootKey, err := db.GetVerifier(ids[0])
   412  	c.Assert(err, IsNil)
   413  
   414  	// generate two targets keys
   415  	generateAndAddPrivateKey(c, r, "targets")
   416  	generateAndAddPrivateKey(c, r, "targets")
   417  
   418  	// check root metadata is correct
   419  	root, err = r.root()
   420  	c.Assert(err, IsNil)
   421  	c.Assert(root.Roles, HasLen, 2)
   422  	rs.assertNumUniqueKeys(c, root, "root", 1)
   423  	rs.assertNumUniqueKeys(c, root, "targets", 2)
   424  	targetsRole, ok := root.Roles["targets"]
   425  	if !ok {
   426  		c.Fatal("missing targets role")
   427  	}
   428  	c.Assert(targetsRole.KeyIDs, HasLen, 2)
   429  	targetKeyIDs := make(map[string]struct{}, 2)
   430  	db, err = r.topLevelKeysDB()
   431  	c.Assert(err, IsNil)
   432  	for _, id := range targetsRole.KeyIDs {
   433  		targetKeyIDs[id] = struct{}{}
   434  		_, ok = root.Keys[id]
   435  		if !ok {
   436  			c.Fatal("missing key")
   437  		}
   438  		verifier, err := db.GetVerifier(id)
   439  		c.Assert(err, IsNil)
   440  		c.Assert(verifier.MarshalPublicKey().ContainsID(id), Equals, true)
   441  	}
   442  	role := db.GetRole("targets")
   443  	c.Assert(role.KeyIDs, DeepEquals, targetKeyIDs)
   444  
   445  	// check RootKeys() is unchanged
   446  	rootKeys, err := r.RootKeys()
   447  	c.Assert(err, IsNil)
   448  	c.Assert(rootKeys, HasLen, 1)
   449  	c.Assert(rootKeys[0].IDs(), DeepEquals, rootKey.MarshalPublicKey().IDs())
   450  
   451  	// check the keys were saved correctly
   452  	localKeys, err := local.GetSigners("targets")
   453  	c.Assert(err, IsNil)
   454  	c.Assert(localKeys, HasLen, 2)
   455  	for _, key := range localKeys {
   456  		found := false
   457  		for _, id := range targetsRole.KeyIDs {
   458  			if key.PublicData().ContainsID(id) {
   459  				found = true
   460  				break
   461  			}
   462  		}
   463  		if !found {
   464  			c.Fatal("missing key")
   465  		}
   466  	}
   467  
   468  	// check root.json got staged
   469  	meta, err := local.GetMeta()
   470  	c.Assert(err, IsNil)
   471  	rootJSON, ok := meta["root.json"]
   472  	if !ok {
   473  		c.Fatal("missing root metadata")
   474  	}
   475  	s := &data.Signed{}
   476  	c.Assert(json.Unmarshal(rootJSON, s), IsNil)
   477  	stagedRoot := &data.Root{}
   478  	c.Assert(json.Unmarshal(s.Signed, stagedRoot), IsNil)
   479  	c.Assert(stagedRoot.Type, Equals, root.Type)
   480  	c.Assert(stagedRoot.Version, Equals, root.Version)
   481  	c.Assert(stagedRoot.Expires.UnixNano(), Equals, root.Expires.UnixNano())
   482  
   483  	// make sure both root and stagedRoot have evaluated IDs(), otherwise
   484  	// DeepEquals will fail because those values might not have been
   485  	// computed yet.
   486  	for _, key := range root.Keys {
   487  		key.IDs()
   488  	}
   489  	for _, key := range stagedRoot.Keys {
   490  		key.IDs()
   491  	}
   492  	c.Assert(stagedRoot.Keys, DeepEquals, root.Keys)
   493  	c.Assert(stagedRoot.Roles, DeepEquals, root.Roles)
   494  
   495  	// commit to make sure we don't modify metadata after committing metadata.
   496  	generateAndAddPrivateKey(c, r, "snapshot")
   497  	generateAndAddPrivateKey(c, r, "timestamp")
   498  	c.Assert(r.AddTargets([]string{}, nil), IsNil)
   499  	c.Assert(r.Snapshot(), IsNil)
   500  	c.Assert(r.Timestamp(), IsNil)
   501  	c.Assert(r.Commit(), IsNil)
   502  
   503  	// add the same root key to make sure the metadata is unmodified.
   504  	oldRoot, err := r.root()
   505  	c.Assert(err, IsNil)
   506  	addPrivateKey(c, r, "root", signer)
   507  	newRoot, err := r.root()
   508  	c.Assert(err, IsNil)
   509  	c.Assert(oldRoot, DeepEquals, newRoot)
   510  	if r.local.FileIsStaged("root.json") {
   511  		c.Fatal("root should not be marked dirty")
   512  	}
   513  }
   514  
   515  func (rs *RepoSuite) TestRevokeKey(c *C) {
   516  	local := MemoryStore(make(map[string]json.RawMessage), nil)
   517  	r, err := NewRepo(local)
   518  	c.Assert(err, IsNil)
   519  
   520  	// revoking a key for an unknown role returns ErrInvalidRole
   521  	c.Assert(r.RevokeKey("foo", ""), DeepEquals, ErrInvalidRole{"foo", "only revocations for top-level roles supported"})
   522  
   523  	// revoking a key which doesn't exist returns ErrKeyNotFound
   524  	c.Assert(r.RevokeKey("root", "nonexistent"), DeepEquals, ErrKeyNotFound{"root", "nonexistent"})
   525  
   526  	// generate keys
   527  	genKey(c, r, "root")
   528  	target1IDs := genKey(c, r, "targets")
   529  	target2IDs := genKey(c, r, "targets")
   530  	genKey(c, r, "snapshot")
   531  	genKey(c, r, "timestamp")
   532  	root, err := r.root()
   533  	c.Assert(err, IsNil)
   534  	c.Assert(root.Roles, NotNil)
   535  	c.Assert(root.Roles, HasLen, 4)
   536  	c.Assert(root.Keys, NotNil)
   537  	rs.assertNumUniqueKeys(c, root, "root", 1)
   538  	rs.assertNumUniqueKeys(c, root, "targets", 2)
   539  	rs.assertNumUniqueKeys(c, root, "snapshot", 1)
   540  	rs.assertNumUniqueKeys(c, root, "timestamp", 1)
   541  
   542  	// revoke a key
   543  	targetsRole, ok := root.Roles["targets"]
   544  	if !ok {
   545  		c.Fatal("missing targets role")
   546  	}
   547  	c.Assert(targetsRole.KeyIDs, HasLen, len(target1IDs)+len(target2IDs))
   548  	id := targetsRole.KeyIDs[0]
   549  	c.Assert(r.RevokeKey("targets", id), IsNil)
   550  
   551  	// make sure all the other key ids were also revoked
   552  	for _, id := range target1IDs {
   553  		c.Assert(r.RevokeKey("targets", id), DeepEquals, ErrKeyNotFound{"targets", id})
   554  	}
   555  
   556  	// check root was updated
   557  	root, err = r.root()
   558  	c.Assert(err, IsNil)
   559  	c.Assert(root.Roles, NotNil)
   560  	c.Assert(root.Roles, HasLen, 4)
   561  	c.Assert(root.Keys, NotNil)
   562  	rs.assertNumUniqueKeys(c, root, "root", 1)
   563  	rs.assertNumUniqueKeys(c, root, "targets", 1)
   564  	rs.assertNumUniqueKeys(c, root, "snapshot", 1)
   565  	rs.assertNumUniqueKeys(c, root, "timestamp", 1)
   566  	targetsRole, ok = root.Roles["targets"]
   567  	if !ok {
   568  		c.Fatal("missing targets role")
   569  	}
   570  	c.Assert(targetsRole.KeyIDs, HasLen, 1)
   571  	c.Assert(targetsRole.KeyIDs, DeepEquals, target2IDs)
   572  }
   573  
   574  func (rs *RepoSuite) TestRevokeKeyInMultipleRoles(c *C) {
   575  	local := MemoryStore(make(map[string]json.RawMessage), nil)
   576  	r, err := NewRepo(local)
   577  	c.Assert(err, IsNil)
   578  
   579  	// generate keys. add a root key that is shared with the targets role
   580  	rootSigner, err := keys.GenerateEd25519Key()
   581  	c.Assert(err, IsNil)
   582  	c.Assert(r.AddVerificationKey("root", rootSigner.PublicData()), IsNil)
   583  	sharedSigner, err := keys.GenerateEd25519Key()
   584  	c.Assert(err, IsNil)
   585  	sharedIDs := sharedSigner.PublicData().IDs()
   586  	c.Assert(r.AddVerificationKey("root", sharedSigner.PublicData()), IsNil)
   587  	c.Assert(r.AddVerificationKey("targets", sharedSigner.PublicData()), IsNil)
   588  	targetIDs := genKey(c, r, "targets")
   589  	genKey(c, r, "snapshot")
   590  	genKey(c, r, "timestamp")
   591  	root, err := r.root()
   592  	c.Assert(err, IsNil)
   593  	c.Assert(root.Roles, NotNil)
   594  	c.Assert(root.Roles, HasLen, 4)
   595  	c.Assert(root.Keys, NotNil)
   596  	rs.assertNumUniqueKeys(c, root, "root", 2)
   597  	rs.assertNumUniqueKeys(c, root, "targets", 2)
   598  	rs.assertNumUniqueKeys(c, root, "snapshot", 1)
   599  	rs.assertNumUniqueKeys(c, root, "timestamp", 1)
   600  
   601  	// revoke a key
   602  	targetsRole, ok := root.Roles["targets"]
   603  	if !ok {
   604  		c.Fatal("missing targets role")
   605  	}
   606  	c.Assert(targetsRole.KeyIDs, HasLen, len(targetIDs)+len(sharedIDs))
   607  	id := targetsRole.KeyIDs[0]
   608  	c.Assert(r.RevokeKey("targets", id), IsNil)
   609  
   610  	// make sure all the other key ids were also revoked
   611  	for _, id := range sharedIDs {
   612  		c.Assert(r.RevokeKey("targets", id), DeepEquals, ErrKeyNotFound{"targets", id})
   613  	}
   614  
   615  	// check root was updated
   616  	root, err = r.root()
   617  	c.Assert(err, IsNil)
   618  	c.Assert(root.Roles, NotNil)
   619  	c.Assert(root.Roles, HasLen, 4)
   620  	c.Assert(root.Keys, NotNil)
   621  	// the shared root/targets signer should still be present in root keys
   622  	c.Assert(UniqueKeys(root)["root"], DeepEquals,
   623  		[]*data.PublicKey{rootSigner.PublicData(), sharedSigner.PublicData()})
   624  	rs.assertNumUniqueKeys(c, root, "root", 2)
   625  	rs.assertNumUniqueKeys(c, root, "targets", 1)
   626  	rs.assertNumUniqueKeys(c, root, "snapshot", 1)
   627  	rs.assertNumUniqueKeys(c, root, "timestamp", 1)
   628  	targetsRole, ok = root.Roles["targets"]
   629  	if !ok {
   630  		c.Fatal("missing targets role")
   631  	}
   632  	c.Assert(targetsRole.KeyIDs, HasLen, 1)
   633  	c.Assert(targetsRole.KeyIDs, DeepEquals, targetIDs)
   634  }
   635  
   636  func (rs *RepoSuite) TestSign(c *C) {
   637  	meta := map[string]json.RawMessage{"root.json": []byte(`{"signed":{},"signatures":[]}`)}
   638  	local := MemoryStore(meta, nil)
   639  	r, err := NewRepo(local)
   640  	c.Assert(err, IsNil)
   641  
   642  	c.Assert(r.Sign("foo.json"), Equals, ErrMissingMetadata{"foo.json"})
   643  
   644  	// signing with no keys returns ErrNoKeys
   645  	c.Assert(r.Sign("root.json"), Equals, ErrNoKeys{"root.json"})
   646  
   647  	checkSigIDs := func(keyIDs ...string) {
   648  		meta, err := local.GetMeta()
   649  		c.Assert(err, IsNil)
   650  		rootJSON, ok := meta["root.json"]
   651  		if !ok {
   652  			c.Fatal("missing root.json")
   653  		}
   654  		s := &data.Signed{}
   655  		c.Assert(json.Unmarshal(rootJSON, s), IsNil)
   656  		c.Assert(s.Signatures, HasLen, len(keyIDs))
   657  
   658  		// Signatures may be in any order, so must sort key IDs before comparison.
   659  		wantKeyIDs := append([]string{}, keyIDs...)
   660  		sort.Strings(wantKeyIDs)
   661  
   662  		gotKeyIDs := []string{}
   663  		for _, sig := range s.Signatures {
   664  			gotKeyIDs = append(gotKeyIDs, sig.KeyID)
   665  		}
   666  		sort.Strings(gotKeyIDs)
   667  
   668  		c.Assert(wantKeyIDs, DeepEquals, gotKeyIDs)
   669  	}
   670  
   671  	// signing with an available key generates a signature
   672  	signer, err := keys.GenerateEd25519Key()
   673  	c.Assert(err, IsNil)
   674  	c.Assert(local.SaveSigner("root", signer), IsNil)
   675  	c.Assert(r.Sign("root.json"), IsNil)
   676  	checkSigIDs(signer.PublicData().IDs()...)
   677  
   678  	// signing again does not generate a duplicate signature
   679  	c.Assert(r.Sign("root.json"), IsNil)
   680  	checkSigIDs(signer.PublicData().IDs()...)
   681  
   682  	// signing with a new available key generates another signature
   683  	newKey, err := keys.GenerateEd25519Key()
   684  	c.Assert(err, IsNil)
   685  	c.Assert(local.SaveSigner("root", newKey), IsNil)
   686  	c.Assert(r.Sign("root.json"), IsNil)
   687  	checkSigIDs(append(signer.PublicData().IDs(), newKey.PublicData().IDs()...)...)
   688  
   689  	// attempt to sign missing metadata
   690  	c.Assert(r.Sign("targets.json"), Equals, ErrMissingMetadata{"targets.json"})
   691  }
   692  
   693  func (rs *RepoSuite) TestStatus(c *C) {
   694  	files := map[string][]byte{"foo.txt": []byte("foo")}
   695  	local := MemoryStore(make(map[string]json.RawMessage), files)
   696  	r, err := NewRepo(local)
   697  	c.Assert(err, IsNil)
   698  
   699  	genKey(c, r, "root")
   700  	genKey(c, r, "targets")
   701  	genKey(c, r, "snapshot")
   702  	genKey(c, r, "timestamp")
   703  
   704  	c.Assert(r.AddTarget("foo.txt", nil), IsNil)
   705  	c.Assert(r.SnapshotWithExpires(time.Now().Add(24*time.Hour)), IsNil)
   706  	c.Assert(r.TimestampWithExpires(time.Now().Add(1*time.Hour)), IsNil)
   707  	c.Assert(r.Commit(), IsNil)
   708  
   709  	expires := time.Now().Add(2 * time.Hour)
   710  	c.Assert(r.CheckRoleUnexpired("timestamp", expires), ErrorMatches, "role expired on.*")
   711  	c.Assert(r.CheckRoleUnexpired("snapshot", expires), IsNil)
   712  	c.Assert(r.CheckRoleUnexpired("targets", expires), IsNil)
   713  	c.Assert(r.CheckRoleUnexpired("root", expires), IsNil)
   714  }
   715  
   716  func (rs *RepoSuite) TestCommit(c *C) {
   717  	files := map[string][]byte{"foo.txt": []byte("foo"), "bar.txt": []byte("bar")}
   718  	local := MemoryStore(make(map[string]json.RawMessage), files)
   719  	r, err := NewRepo(local)
   720  	c.Assert(err, IsNil)
   721  
   722  	// commit without root.json
   723  	c.Assert(r.Commit(), DeepEquals, ErrMissingMetadata{"root.json"})
   724  
   725  	// Init should create targets.json, but not signed yet
   726  	r.Init(false)
   727  	c.Assert(r.Commit(), DeepEquals, ErrMissingMetadata{"snapshot.json"})
   728  
   729  	genKey(c, r, "root")
   730  
   731  	// commit without snapshot.json
   732  	genKey(c, r, "targets")
   733  	c.Assert(r.Sign("targets.json"), IsNil)
   734  	c.Assert(r.Commit(), DeepEquals, ErrMissingMetadata{"snapshot.json"})
   735  
   736  	// commit without timestamp.json
   737  	genKey(c, r, "snapshot")
   738  	c.Assert(r.Snapshot(), IsNil)
   739  	c.Assert(r.Commit(), DeepEquals, ErrMissingMetadata{"timestamp.json"})
   740  
   741  	// commit with timestamp.json but no timestamp key
   742  	c.Assert(r.Timestamp(), IsNil)
   743  	c.Assert(r.Commit(), DeepEquals, ErrInsufficientSignatures{"timestamp.json", verify.ErrNoSignatures})
   744  
   745  	// commit success
   746  	genKey(c, r, "timestamp")
   747  	c.Assert(r.Snapshot(), IsNil)
   748  	c.Assert(r.Timestamp(), IsNil)
   749  	c.Assert(r.Commit(), IsNil)
   750  
   751  	// commit with an invalid root hash in snapshot.json due to new key creation
   752  	genKey(c, r, "targets")
   753  	c.Assert(r.Sign("targets.json"), IsNil)
   754  	c.Assert(r.Commit(), DeepEquals, errors.New("tuf: invalid targets.json in snapshot.json: wrong length, expected 338 got 552"))
   755  
   756  	// commit with an invalid targets hash in snapshot.json
   757  	c.Assert(r.Snapshot(), IsNil)
   758  	c.Assert(r.AddTarget("bar.txt", nil), IsNil)
   759  	c.Assert(r.Commit(), DeepEquals, errors.New("tuf: invalid targets.json in snapshot.json: wrong length, expected 552 got 725"))
   760  
   761  	// commit with an invalid timestamp
   762  	c.Assert(r.Snapshot(), IsNil)
   763  	err = r.Commit()
   764  	c.Assert(err, NotNil)
   765  	c.Assert(err.Error()[0:44], Equals, "tuf: invalid snapshot.json in timestamp.json")
   766  
   767  	// commit with a role's threshold greater than number of keys
   768  	root, err := r.root()
   769  	c.Assert(err, IsNil)
   770  	role, ok := root.Roles["timestamp"]
   771  	if !ok {
   772  		c.Fatal("missing timestamp role")
   773  	}
   774  	c.Assert(role.KeyIDs, HasLen, 1)
   775  	c.Assert(role.Threshold, Equals, 1)
   776  	c.Assert(r.RevokeKey("timestamp", role.KeyIDs[0]), IsNil)
   777  	c.Assert(r.Snapshot(), IsNil)
   778  	c.Assert(r.Timestamp(), IsNil)
   779  	c.Assert(r.Commit(), DeepEquals, ErrNotEnoughKeys{"timestamp", 0, 1})
   780  }
   781  
   782  func (rs *RepoSuite) TestCommitVersions(c *C) {
   783  	files := map[string][]byte{"foo.txt": []byte("foo")}
   784  	local := MemoryStore(make(map[string]json.RawMessage), files)
   785  	r, err := NewRepo(local)
   786  	c.Assert(err, IsNil)
   787  
   788  	genKey(c, r, "root")
   789  	genKey(c, r, "targets")
   790  	genKey(c, r, "snapshot")
   791  	genKey(c, r, "timestamp")
   792  
   793  	c.Assert(r.AddTarget("foo.txt", nil), IsNil)
   794  	c.Assert(r.Snapshot(), IsNil)
   795  	c.Assert(r.Timestamp(), IsNil)
   796  	c.Assert(r.Commit(), IsNil)
   797  
   798  	// on initial commit everything should be at version 1.
   799  	rootVersion, err := r.RootVersion()
   800  	c.Assert(err, IsNil)
   801  	c.Assert(rootVersion, Equals, int64(1))
   802  
   803  	targetsVersion, err := r.TargetsVersion()
   804  	c.Assert(err, IsNil)
   805  	c.Assert(targetsVersion, Equals, int64(1))
   806  
   807  	snapshotVersion, err := r.SnapshotVersion()
   808  	c.Assert(err, IsNil)
   809  	c.Assert(snapshotVersion, Equals, int64(1))
   810  
   811  	timestampVersion, err := r.SnapshotVersion()
   812  	c.Assert(err, IsNil)
   813  	c.Assert(timestampVersion, Equals, int64(1))
   814  
   815  	// taking a snapshot should only increment snapshot and timestamp.
   816  	c.Assert(r.Snapshot(), IsNil)
   817  	c.Assert(r.Timestamp(), IsNil)
   818  	c.Assert(r.Commit(), IsNil)
   819  
   820  	rootVersion, err = r.RootVersion()
   821  	c.Assert(err, IsNil)
   822  	c.Assert(rootVersion, Equals, int64(1))
   823  
   824  	targetsVersion, err = r.TargetsVersion()
   825  	c.Assert(err, IsNil)
   826  	c.Assert(targetsVersion, Equals, int64(1))
   827  
   828  	snapshotVersion, err = r.SnapshotVersion()
   829  	c.Assert(err, IsNil)
   830  	c.Assert(snapshotVersion, Equals, int64(2))
   831  
   832  	timestampVersion, err = r.SnapshotVersion()
   833  	c.Assert(err, IsNil)
   834  	c.Assert(timestampVersion, Equals, int64(2))
   835  
   836  	// rotating multiple keys should increment the root once.
   837  	genKey(c, r, "targets")
   838  	genKey(c, r, "snapshot")
   839  	genKey(c, r, "timestamp")
   840  	c.Assert(r.Snapshot(), IsNil)
   841  	c.Assert(r.Timestamp(), IsNil)
   842  	c.Assert(r.Commit(), IsNil)
   843  
   844  	rootVersion, err = r.RootVersion()
   845  	c.Assert(err, IsNil)
   846  	c.Assert(rootVersion, Equals, int64(2))
   847  
   848  	targetsVersion, err = r.TargetsVersion()
   849  	c.Assert(err, IsNil)
   850  	c.Assert(targetsVersion, Equals, int64(1))
   851  
   852  	snapshotVersion, err = r.SnapshotVersion()
   853  	c.Assert(err, IsNil)
   854  	c.Assert(snapshotVersion, Equals, int64(3))
   855  
   856  	timestampVersion, err = r.TimestampVersion()
   857  	c.Assert(err, IsNil)
   858  	c.Assert(timestampVersion, Equals, int64(3))
   859  }
   860  
   861  type tmpDir struct {
   862  	path string
   863  	c    *C
   864  }
   865  
   866  func newTmpDir(c *C) *tmpDir {
   867  	return &tmpDir{path: c.MkDir(), c: c}
   868  }
   869  
   870  func (t *tmpDir) assertExists(path string) {
   871  	if _, err := os.Stat(filepath.Join(t.path, path)); os.IsNotExist(err) {
   872  		t.c.Fatalf("expected path to exist but it doesn't: %s", path)
   873  	}
   874  }
   875  
   876  func (t *tmpDir) assertNotExist(path string) {
   877  	if _, err := os.Stat(filepath.Join(t.path, path)); !os.IsNotExist(err) {
   878  		t.c.Fatalf("expected path to not exist but it does: %s", path)
   879  	}
   880  }
   881  
   882  func (t *tmpDir) assertHashedFilesExist(path string, hashes data.Hashes) {
   883  	t.c.Assert(len(hashes) > 0, Equals, true)
   884  	for _, path := range util.HashedPaths(path, hashes) {
   885  		t.assertExists(path)
   886  	}
   887  }
   888  
   889  func (t *tmpDir) assertHashedFilesNotExist(path string, hashes data.Hashes) {
   890  	for _, path := range util.HashedPaths(path, hashes) {
   891  		t.assertNotExist(path)
   892  	}
   893  }
   894  
   895  func (t *tmpDir) assertVersionedFileExist(path string, version int64) {
   896  	t.assertExists(util.VersionedPath(path, version))
   897  }
   898  
   899  func (t *tmpDir) assertVersionedFileNotExist(path string, version int64) {
   900  	t.assertNotExist(util.VersionedPath(path, version))
   901  }
   902  
   903  func (t *tmpDir) assertEmpty(dir string) {
   904  	path := filepath.Join(t.path, dir)
   905  	f, err := os.Stat(path)
   906  	if os.IsNotExist(err) {
   907  		t.c.Fatalf("expected dir to exist but it doesn't: %s", dir)
   908  	}
   909  	t.c.Assert(err, IsNil)
   910  	t.c.Assert(f.IsDir(), Equals, true)
   911  
   912  	entries, err := os.ReadDir(path)
   913  	t.c.Assert(err, IsNil)
   914  	// check that all (if any) entries are also empty
   915  	for _, e := range entries {
   916  		t.assertEmpty(filepath.Join(dir, e.Name()))
   917  	}
   918  }
   919  
   920  func (t *tmpDir) assertFileContent(path, content string) {
   921  	actual := t.readFile(path)
   922  	t.c.Assert(string(actual), Equals, content)
   923  }
   924  
   925  func (t *tmpDir) stagedTargetPath(path string) string {
   926  	return filepath.Join(t.path, "staged", "targets", path)
   927  }
   928  
   929  func (t *tmpDir) writeStagedTarget(path, data string) {
   930  	path = t.stagedTargetPath(path)
   931  	t.c.Assert(os.MkdirAll(filepath.Dir(path), 0755), IsNil)
   932  	t.c.Assert(os.WriteFile(path, []byte(data), 0644), IsNil)
   933  }
   934  
   935  func (t *tmpDir) readFile(path string) []byte {
   936  	t.assertExists(path)
   937  	data, err := os.ReadFile(filepath.Join(t.path, path))
   938  	t.c.Assert(err, IsNil)
   939  	return data
   940  }
   941  
   942  func (rs *RepoSuite) TestCommitFileSystem(c *C) {
   943  	tmp := newTmpDir(c)
   944  	local := FileSystemStore(tmp.path, nil)
   945  	r, err := NewRepo(local)
   946  	c.Assert(err, IsNil)
   947  
   948  	// don't use consistent snapshots to make the checks simpler
   949  	c.Assert(r.Init(false), IsNil)
   950  
   951  	// cleaning with nothing staged or committed should fail
   952  	c.Assert(r.Clean(), Equals, ErrNewRepository)
   953  
   954  	// generating keys should stage root.json and create repo dirs
   955  	genKey(c, r, "root")
   956  	genKey(c, r, "targets")
   957  	genKey(c, r, "snapshot")
   958  	genKey(c, r, "timestamp")
   959  	tmp.assertExists("staged/root.json")
   960  	tmp.assertEmpty("repository")
   961  	tmp.assertEmpty("staged/targets")
   962  
   963  	// cleaning with nothing committed should fail
   964  	c.Assert(r.Clean(), Equals, ErrNewRepository)
   965  
   966  	// adding a non-existent file fails
   967  	c.Assert(r.AddTarget("foo.txt", nil), Equals, ErrFileNotFound{tmp.stagedTargetPath("foo.txt")})
   968  	tmp.assertEmpty("repository")
   969  
   970  	// adding a file stages targets.json
   971  	tmp.writeStagedTarget("foo.txt", "foo")
   972  	c.Assert(r.AddTarget("foo.txt", nil), IsNil)
   973  	tmp.assertExists("staged/targets.json")
   974  	tmp.assertEmpty("repository")
   975  	t, err := r.topLevelTargets()
   976  	c.Assert(err, IsNil)
   977  	c.Assert(t.Targets, HasLen, 1)
   978  	if _, ok := t.Targets["foo.txt"]; !ok {
   979  		c.Fatal("missing target file: foo.txt")
   980  	}
   981  
   982  	// Snapshot() stages snapshot.json
   983  	c.Assert(r.Snapshot(), IsNil)
   984  	tmp.assertExists("staged/snapshot.json")
   985  	tmp.assertEmpty("repository")
   986  
   987  	// Timestamp() stages timestamp.json
   988  	c.Assert(r.Timestamp(), IsNil)
   989  	tmp.assertExists("staged/timestamp.json")
   990  	tmp.assertEmpty("repository")
   991  
   992  	// committing moves files from staged -> repository
   993  	c.Assert(r.Commit(), IsNil)
   994  	tmp.assertExists("repository/root.json")
   995  	tmp.assertExists("repository/targets.json")
   996  	tmp.assertExists("repository/snapshot.json")
   997  	tmp.assertExists("repository/timestamp.json")
   998  	tmp.assertFileContent("repository/targets/foo.txt", "foo")
   999  	tmp.assertEmpty("staged/targets")
  1000  	tmp.assertEmpty("staged")
  1001  
  1002  	// adding and committing another file moves it into repository/targets
  1003  	tmp.writeStagedTarget("path/to/bar.txt", "bar")
  1004  	c.Assert(r.AddTarget("path/to/bar.txt", nil), IsNil)
  1005  	tmp.assertExists("staged/targets.json")
  1006  	c.Assert(r.Snapshot(), IsNil)
  1007  	c.Assert(r.Timestamp(), IsNil)
  1008  	c.Assert(r.Commit(), IsNil)
  1009  	tmp.assertFileContent("repository/targets/foo.txt", "foo")
  1010  	tmp.assertFileContent("repository/targets/path/to/bar.txt", "bar")
  1011  	tmp.assertEmpty("staged/targets")
  1012  	tmp.assertEmpty("staged")
  1013  
  1014  	// removing and committing a file removes it from repository/targets
  1015  	c.Assert(r.RemoveTarget("foo.txt"), IsNil)
  1016  	tmp.assertExists("staged/targets.json")
  1017  	c.Assert(r.Snapshot(), IsNil)
  1018  	c.Assert(r.Timestamp(), IsNil)
  1019  	c.Assert(r.Commit(), IsNil)
  1020  	tmp.assertNotExist("repository/targets/foo.txt")
  1021  	tmp.assertFileContent("repository/targets/path/to/bar.txt", "bar")
  1022  	tmp.assertEmpty("staged/targets")
  1023  	tmp.assertEmpty("staged")
  1024  }
  1025  
  1026  func (rs *RepoSuite) TestCommitFileSystemWithNewRepositories(c *C) {
  1027  	tmp := newTmpDir(c)
  1028  
  1029  	newRepo := func() *Repo {
  1030  		local := FileSystemStore(tmp.path, nil)
  1031  		r, err := NewRepo(local)
  1032  		c.Assert(err, IsNil)
  1033  		return r
  1034  	}
  1035  
  1036  	genKey(c, newRepo(), "root")
  1037  	genKey(c, newRepo(), "targets")
  1038  	genKey(c, newRepo(), "snapshot")
  1039  	genKey(c, newRepo(), "timestamp")
  1040  
  1041  	tmp.writeStagedTarget("foo.txt", "foo")
  1042  	c.Assert(newRepo().AddTarget("foo.txt", nil), IsNil)
  1043  	c.Assert(newRepo().Snapshot(), IsNil)
  1044  	c.Assert(newRepo().Timestamp(), IsNil)
  1045  	c.Assert(newRepo().Commit(), IsNil)
  1046  }
  1047  
  1048  func (rs *RepoSuite) TestConsistentSnapshot(c *C) {
  1049  	tmp := newTmpDir(c)
  1050  	local := FileSystemStore(tmp.path, nil)
  1051  	r, err := NewRepo(local, "sha512", "sha256")
  1052  	c.Assert(err, IsNil)
  1053  
  1054  	genKey(c, r, "root")
  1055  	genKey(c, r, "targets")
  1056  	genKey(c, r, "snapshot")
  1057  	genKey(c, r, "timestamp")
  1058  	tmp.writeStagedTarget("foo.txt", "foo")
  1059  	c.Assert(r.AddTarget("foo.txt", nil), IsNil)
  1060  	tmp.writeStagedTarget("dir/bar.txt", "bar")
  1061  	c.Assert(r.AddTarget("dir/bar.txt", nil), IsNil)
  1062  	c.Assert(r.Snapshot(), IsNil)
  1063  	c.Assert(r.Timestamp(), IsNil)
  1064  	c.Assert(r.Commit(), IsNil)
  1065  
  1066  	versions, err := r.fileVersions()
  1067  	c.Assert(err, IsNil)
  1068  	c.Assert(versions["root.json"], Equals, int64(1))
  1069  	c.Assert(versions["targets.json"], Equals, int64(1))
  1070  	c.Assert(versions["snapshot.json"], Equals, int64(1))
  1071  
  1072  	hashes, err := r.fileHashes()
  1073  	c.Assert(err, IsNil)
  1074  
  1075  	// root.json, targets.json and snapshot.json should exist at both versioned and unversioned paths
  1076  	for _, meta := range []string{"root.json", "targets.json", "snapshot.json"} {
  1077  		repoPath := path.Join("repository", meta)
  1078  		if meta != "root.json" {
  1079  			c.Assert(len(hashes[meta]) > 0, Equals, true)
  1080  		}
  1081  		tmp.assertHashedFilesNotExist(repoPath, hashes[meta])
  1082  		tmp.assertVersionedFileExist(repoPath, versions[meta])
  1083  		tmp.assertExists(repoPath)
  1084  	}
  1085  
  1086  	// target files should exist at hashed but not unhashed paths
  1087  	for _, target := range []string{"targets/foo.txt", "targets/dir/bar.txt"} {
  1088  		repoPath := path.Join("repository", target)
  1089  		tmp.assertHashedFilesExist(repoPath, hashes[target])
  1090  		tmp.assertNotExist(repoPath)
  1091  	}
  1092  
  1093  	// timestamp.json should exist at an unversioned and unhashed path (it doesn't have a hash)
  1094  	c.Assert(hashes["repository/timestamp.json"], IsNil)
  1095  	tmp.assertVersionedFileNotExist("repository/timestamp.json", versions["repository/timestamp.json"])
  1096  	tmp.assertExists("repository/timestamp.json")
  1097  
  1098  	// removing a file should remove the hashed files
  1099  	c.Assert(r.RemoveTarget("foo.txt"), IsNil)
  1100  	c.Assert(r.Snapshot(), IsNil)
  1101  	c.Assert(r.Timestamp(), IsNil)
  1102  	c.Assert(r.Commit(), IsNil)
  1103  
  1104  	versions, err = r.fileVersions()
  1105  	c.Assert(err, IsNil)
  1106  	c.Assert(versions["root.json"], Equals, int64(1))
  1107  	c.Assert(versions["targets.json"], Equals, int64(2))
  1108  	c.Assert(versions["snapshot.json"], Equals, int64(2))
  1109  
  1110  	// Save the old hashes for foo.txt to make sure we can assert it doesn't exist later.
  1111  	fooHashes := hashes["targets/foo.txt"]
  1112  	hashes, err = r.fileHashes()
  1113  	c.Assert(err, IsNil)
  1114  
  1115  	// root.json, targets.json and snapshot.json should exist at both versioned and unversioned paths
  1116  	for _, meta := range []string{"root.json", "targets.json", "snapshot.json"} {
  1117  		repoPath := path.Join("repository", meta)
  1118  		if meta != "root.json" {
  1119  			c.Assert(len(hashes[meta]) > 0, Equals, true)
  1120  		}
  1121  		tmp.assertHashedFilesNotExist(repoPath, hashes[meta])
  1122  		tmp.assertVersionedFileExist(repoPath, versions[meta])
  1123  		tmp.assertExists(repoPath)
  1124  	}
  1125  
  1126  	tmp.assertHashedFilesNotExist("repository/targets/foo.txt", fooHashes)
  1127  	tmp.assertNotExist("repository/targets/foo.txt")
  1128  
  1129  	// targets should be returned by new repo
  1130  	newRepo, err := NewRepo(local, "sha512", "sha256")
  1131  	c.Assert(err, IsNil)
  1132  	t, err := newRepo.topLevelTargets()
  1133  	c.Assert(err, IsNil)
  1134  	c.Assert(t.Targets, HasLen, 1)
  1135  	if _, ok := t.Targets["dir/bar.txt"]; !ok {
  1136  		c.Fatal("missing targets file: dir/bar.txt")
  1137  	}
  1138  }
  1139  
  1140  func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
  1141  	files := map[string][]byte{"foo.txt": []byte("foo")}
  1142  	local := MemoryStore(make(map[string]json.RawMessage), files)
  1143  	r, err := NewRepo(local)
  1144  	c.Assert(err, IsNil)
  1145  
  1146  	past := time.Now().Add(-1 * time.Second)
  1147  	_, genKeyErr := r.GenKeyWithExpires("root", past)
  1148  	for _, err := range []error{
  1149  		genKeyErr,
  1150  		r.AddTargetWithExpires("foo.txt", nil, past),
  1151  		r.RemoveTargetWithExpires("foo.txt", past),
  1152  		r.SnapshotWithExpires(past),
  1153  		r.TimestampWithExpires(past),
  1154  	} {
  1155  		c.Assert(err, Equals, ErrInvalidExpires{past})
  1156  	}
  1157  
  1158  	genKey(c, r, "root")
  1159  	genKey(c, r, "targets")
  1160  	genKey(c, r, "snapshot")
  1161  	genKey(c, r, "timestamp")
  1162  
  1163  	c.Assert(r.AddTargets([]string{}, nil), IsNil)
  1164  	c.Assert(r.Snapshot(), IsNil)
  1165  	c.Assert(r.Timestamp(), IsNil)
  1166  	c.Assert(r.Commit(), IsNil)
  1167  
  1168  	root, err := r.root()
  1169  	c.Assert(err, IsNil)
  1170  	c.Assert(root.Version, Equals, int64(1))
  1171  
  1172  	expires := time.Now().Add(24 * time.Hour)
  1173  	_, err = r.GenKeyWithExpires("root", expires)
  1174  	c.Assert(err, IsNil)
  1175  	c.Assert(r.Snapshot(), IsNil)
  1176  	c.Assert(r.Timestamp(), IsNil)
  1177  	c.Assert(r.Commit(), IsNil)
  1178  	root, err = r.root()
  1179  	c.Assert(err, IsNil)
  1180  	c.Assert(root.Expires.Unix(), DeepEquals, expires.Round(time.Second).Unix())
  1181  	c.Assert(root.Version, Equals, int64(2))
  1182  
  1183  	expires = time.Now().Add(12 * time.Hour)
  1184  	role, ok := root.Roles["root"]
  1185  	if !ok {
  1186  		c.Fatal("missing root role")
  1187  	}
  1188  	c.Assert(role.KeyIDs, HasLen, 2)
  1189  	c.Assert(r.RevokeKeyWithExpires("root", role.KeyIDs[0], expires), IsNil)
  1190  	c.Assert(r.Snapshot(), IsNil)
  1191  	c.Assert(r.Timestamp(), IsNil)
  1192  	c.Assert(r.Commit(), IsNil)
  1193  	root, err = r.root()
  1194  	c.Assert(err, IsNil)
  1195  	c.Assert(root.Expires.Unix(), DeepEquals, expires.Round(time.Second).Unix())
  1196  	c.Assert(root.Version, Equals, int64(3))
  1197  
  1198  	expires = time.Now().Add(6 * time.Hour)
  1199  	c.Assert(r.AddTargetWithExpires("foo.txt", nil, expires), IsNil)
  1200  	c.Assert(r.Snapshot(), IsNil)
  1201  	c.Assert(r.Timestamp(), IsNil)
  1202  	c.Assert(r.Commit(), IsNil)
  1203  	targets, err := r.topLevelTargets()
  1204  	c.Assert(err, IsNil)
  1205  	c.Assert(targets.Expires.Unix(), Equals, expires.Round(time.Second).Unix())
  1206  	c.Assert(targets.Version, Equals, int64(2))
  1207  
  1208  	expires = time.Now().Add(2 * time.Hour)
  1209  	c.Assert(r.RemoveTargetWithExpires("foo.txt", expires), IsNil)
  1210  	c.Assert(r.Snapshot(), IsNil)
  1211  	c.Assert(r.Timestamp(), IsNil)
  1212  	c.Assert(r.Commit(), IsNil)
  1213  	targets, err = r.topLevelTargets()
  1214  	c.Assert(err, IsNil)
  1215  	c.Assert(targets.Expires.Unix(), Equals, expires.Round(time.Second).Unix())
  1216  	c.Assert(targets.Version, Equals, int64(3))
  1217  
  1218  	expires = time.Now().Add(time.Hour)
  1219  	c.Assert(r.SnapshotWithExpires(expires), IsNil)
  1220  	c.Assert(r.Timestamp(), IsNil)
  1221  	c.Assert(r.Commit(), IsNil)
  1222  	snapshot, err := r.snapshot()
  1223  	c.Assert(err, IsNil)
  1224  	c.Assert(snapshot.Expires.Unix(), Equals, expires.Round(time.Second).Unix())
  1225  	c.Assert(snapshot.Version, Equals, int64(6))
  1226  
  1227  	_, snapshotHasRoot := snapshot.Meta["root.json"]
  1228  	c.Assert(snapshotHasRoot, Equals, false)
  1229  	c.Assert(snapshot.Meta["targets.json"].Version, Equals, targets.Version)
  1230  
  1231  	c.Assert(r.Snapshot(), IsNil)
  1232  	c.Assert(r.Timestamp(), IsNil)
  1233  	c.Assert(r.Commit(), IsNil)
  1234  	snapshot, err = r.snapshot()
  1235  	c.Assert(err, IsNil)
  1236  	c.Assert(snapshot.Version, Equals, int64(7))
  1237  
  1238  	expires = time.Now().Add(10 * time.Minute)
  1239  	c.Assert(r.TimestampWithExpires(expires), IsNil)
  1240  	c.Assert(r.Commit(), IsNil)
  1241  	timestamp, err := r.timestamp()
  1242  	c.Assert(err, IsNil)
  1243  	c.Assert(timestamp.Expires.Unix(), Equals, expires.Round(time.Second).Unix())
  1244  	c.Assert(timestamp.Version, Equals, int64(8))
  1245  
  1246  	c.Assert(r.Timestamp(), IsNil)
  1247  	c.Assert(r.Commit(), IsNil)
  1248  	timestamp, err = r.timestamp()
  1249  	c.Assert(err, IsNil)
  1250  	c.Assert(timestamp.Version, Equals, int64(9))
  1251  	c.Assert(timestamp.Meta["snapshot.json"].Version, Equals, snapshot.Version)
  1252  }
  1253  
  1254  func (rs *RepoSuite) TestHashAlgorithm(c *C) {
  1255  	files := map[string][]byte{"foo.txt": []byte("foo")}
  1256  	local := MemoryStore(make(map[string]json.RawMessage), files)
  1257  	type hashTest struct {
  1258  		args     []string
  1259  		expected []string
  1260  	}
  1261  	for _, test := range []hashTest{
  1262  		{args: []string{}, expected: []string{"sha512"}},
  1263  		{args: []string{"sha256"}},
  1264  		{args: []string{"sha512", "sha256"}},
  1265  	} {
  1266  		// generate metadata with specific hash functions
  1267  		r, err := NewRepo(local, test.args...)
  1268  		c.Assert(err, IsNil)
  1269  		genKey(c, r, "root")
  1270  		genKey(c, r, "targets")
  1271  		genKey(c, r, "snapshot")
  1272  		c.Assert(r.AddTarget("foo.txt", nil), IsNil)
  1273  		c.Assert(r.Snapshot(), IsNil)
  1274  		c.Assert(r.Timestamp(), IsNil)
  1275  
  1276  		// check metadata has correct hash functions
  1277  		if test.expected == nil {
  1278  			test.expected = test.args
  1279  		}
  1280  		targets, err := r.topLevelTargets()
  1281  		c.Assert(err, IsNil)
  1282  		snapshot, err := r.snapshot()
  1283  		c.Assert(err, IsNil)
  1284  		timestamp, err := r.timestamp()
  1285  		c.Assert(err, IsNil)
  1286  		for name, file := range map[string]data.FileMeta{
  1287  			"foo.txt":       targets.Targets["foo.txt"].FileMeta,
  1288  			"targets.json":  {Length: snapshot.Meta["targets.json"].Length, Hashes: snapshot.Meta["targets.json"].Hashes},
  1289  			"snapshot.json": {Length: timestamp.Meta["snapshot.json"].Length, Hashes: timestamp.Meta["snapshot.json"].Hashes},
  1290  		} {
  1291  			for _, hashAlgorithm := range test.expected {
  1292  				if _, ok := file.Hashes[hashAlgorithm]; !ok {
  1293  					c.Fatalf("expected %s hash to contain hash func %s, got %s", name, hashAlgorithm, file.Hashes.HashAlgorithms())
  1294  				}
  1295  			}
  1296  		}
  1297  	}
  1298  }
  1299  
  1300  func (rs *RepoSuite) TestKeyPersistence(c *C) {
  1301  	tmp := newTmpDir(c)
  1302  	oldPassphrase := []byte("old_s3cr3t")
  1303  	newPassphrase := []byte("new_s3cr3t")
  1304  	// returnNewPassphrase is used to force the passphrase function to return the new passphrase when called by the SaveSigner() method
  1305  	returnNewPassphrase := false
  1306  	// passphrase mock function
  1307  	testPassphraseFunc := func(a string, b, change bool) ([]byte, error) {
  1308  		if change || returnNewPassphrase {
  1309  			return newPassphrase, nil
  1310  		}
  1311  		return oldPassphrase, nil
  1312  	}
  1313  	store := FileSystemStore(tmp.path, testPassphraseFunc)
  1314  
  1315  	assertKeys := func(role string, enc bool, expected []*data.PrivateKey) {
  1316  		keysJSON := tmp.readFile("keys/" + role + ".json")
  1317  		pk := &persistedKeys{}
  1318  		c.Assert(json.Unmarshal(keysJSON, pk), IsNil)
  1319  
  1320  		// check the persisted keys are correct
  1321  		var actual []*data.PrivateKey
  1322  		pass := oldPassphrase
  1323  		if enc {
  1324  			c.Assert(pk.Encrypted, Equals, true)
  1325  			if returnNewPassphrase {
  1326  				pass = newPassphrase
  1327  			}
  1328  			decrypted, err := encrypted.Decrypt(pk.Data, pass)
  1329  			c.Assert(err, IsNil)
  1330  			c.Assert(json.Unmarshal(decrypted, &actual), IsNil)
  1331  		} else {
  1332  			c.Assert(pk.Encrypted, Equals, false)
  1333  			c.Assert(json.Unmarshal(pk.Data, &actual), IsNil)
  1334  		}
  1335  
  1336  		// Compare slices of unique elements disregarding order.
  1337  		c.Assert(actual, HasLen, len(expected))
  1338  		for _, gotKey := range actual {
  1339  			expectedNumMatches := 0
  1340  			for _, x := range actual {
  1341  				if reflect.DeepEqual(gotKey, x) {
  1342  					expectedNumMatches++
  1343  				}
  1344  			}
  1345  
  1346  			numMatches := 0
  1347  			for _, wantKey := range expected {
  1348  				wantCanon, err := cjson.EncodeCanonical(wantKey)
  1349  				c.Assert(err, IsNil)
  1350  
  1351  				gotCanon, err := cjson.EncodeCanonical(gotKey)
  1352  				c.Assert(err, IsNil)
  1353  
  1354  				if string(wantCanon) == string(gotCanon) {
  1355  					numMatches++
  1356  				}
  1357  			}
  1358  
  1359  			c.Assert(numMatches, Equals, expectedNumMatches, Commentf("actual: %+v, expected: %+v", actual, expected))
  1360  		}
  1361  
  1362  		// check GetKeys is correct
  1363  		signers, err := store.GetSigners(role)
  1364  		c.Assert(err, IsNil)
  1365  
  1366  		// Compare slices of unique elements disregarding order.
  1367  		c.Assert(signers, HasLen, len(expected))
  1368  		for _, s := range signers {
  1369  			expectedNumMatches := 0
  1370  			for _, x := range signers {
  1371  				if reflect.DeepEqual(s, x) {
  1372  					expectedNumMatches++
  1373  				}
  1374  			}
  1375  
  1376  			numMatches := 0
  1377  			for _, e := range expected {
  1378  				v, err := keys.GetSigner(e)
  1379  				c.Assert(err, IsNil)
  1380  
  1381  				if reflect.DeepEqual(s.PublicData().IDs(), v.PublicData().IDs()) {
  1382  					numMatches++
  1383  				}
  1384  			}
  1385  
  1386  			c.Assert(numMatches, Equals, expectedNumMatches, Commentf("signers: %+v, expected: %+v", signers, expected))
  1387  		}
  1388  	}
  1389  
  1390  	// save a key and check it gets encrypted
  1391  	signer, err := keys.GenerateEd25519Key()
  1392  	c.Assert(err, IsNil)
  1393  	privateKey, err := signer.MarshalPrivateKey()
  1394  	c.Assert(err, IsNil)
  1395  	c.Assert(store.SaveSigner("root", signer), IsNil)
  1396  	assertKeys("root", true, []*data.PrivateKey{privateKey})
  1397  
  1398  	// save another key and check it gets added to the existing keys
  1399  	newKey, err := keys.GenerateEd25519Key()
  1400  	c.Assert(err, IsNil)
  1401  	newPrivateKey, err := newKey.MarshalPrivateKey()
  1402  	c.Assert(err, IsNil)
  1403  	c.Assert(store.SaveSigner("root", newKey), IsNil)
  1404  	assertKeys("root", true, []*data.PrivateKey{privateKey, newPrivateKey})
  1405  
  1406  	// check saving a key to an encrypted file without a passphrase fails
  1407  	insecureStore := FileSystemStore(tmp.path, nil)
  1408  	signer, err = keys.GenerateEd25519Key()
  1409  	c.Assert(err, IsNil)
  1410  	c.Assert(insecureStore.SaveSigner("root", signer), Equals, ErrPassphraseRequired{"root"})
  1411  
  1412  	// save a key to an insecure store and check it is not encrypted
  1413  	signer, err = keys.GenerateEd25519Key()
  1414  	c.Assert(err, IsNil)
  1415  	privateKey, err = signer.MarshalPrivateKey()
  1416  	c.Assert(err, IsNil)
  1417  	c.Assert(insecureStore.SaveSigner("targets", signer), IsNil)
  1418  	assertKeys("targets", false, []*data.PrivateKey{privateKey})
  1419  
  1420  	c.Assert(insecureStore.SaveSigner("foo", signer), IsNil)
  1421  	assertKeys("foo", false, []*data.PrivateKey{privateKey})
  1422  
  1423  	// Test changing the passphrase
  1424  	// 1. Create a secure store with a passphrase (create new object and temp folder so we discard any previous state)
  1425  	tmp = newTmpDir(c)
  1426  	var logBytes bytes.Buffer
  1427  	storeOpts := StoreOpts{
  1428  		Logger:   log.New(&logBytes, "", 0),
  1429  		PassFunc: testPassphraseFunc,
  1430  	}
  1431  	store = FileSystemStoreWithOpts(tmp.path, storeOpts)
  1432  
  1433  	// 1.5. Changing passphrase works for top-level and delegated roles.
  1434  	r, err := NewRepo(store)
  1435  	c.Assert(err, IsNil)
  1436  
  1437  	c.Assert(r.ChangePassphrase("targets"), NotNil)
  1438  	c.Assert(r.ChangePassphrase("foo"), NotNil)
  1439  
  1440  	// 2. Test changing the passphrase when the keys file does not exist - should FAIL
  1441  	c.Assert(store.(PassphraseChanger).ChangePassphrase("root"), NotNil)
  1442  	c.Assert(strings.Contains(logBytes.String(), "Missing keys file"), Equals, true)
  1443  
  1444  	// 3. Generate a new key
  1445  	signer, err = keys.GenerateEd25519Key()
  1446  	c.Assert(err, IsNil)
  1447  	privateKey, err = signer.MarshalPrivateKey()
  1448  	c.Assert(err, IsNil)
  1449  	c.Assert(store.SaveSigner("root", signer), IsNil)
  1450  
  1451  	// 4. Verify the key file can be decrypted using the original passphrase - should SUCCEED
  1452  	assertKeys("root", true, []*data.PrivateKey{privateKey})
  1453  
  1454  	// 5. Change the passphrase (our mock passphrase function is called with change=true thus returning the newPassphrase value)
  1455  	c.Assert(store.(PassphraseChanger).ChangePassphrase("root"), IsNil)
  1456  
  1457  	// 6. Try to add a key and implicitly decrypt the keys file using the OLD passphrase - should FAIL
  1458  	newKey, err = keys.GenerateEd25519Key()
  1459  	c.Assert(err, IsNil)
  1460  	_, err = newKey.MarshalPrivateKey()
  1461  	c.Assert(err, IsNil)
  1462  	c.Assert(store.SaveSigner("root", newKey), NotNil)
  1463  
  1464  	// 7. Try to add a key and implicitly decrypt the keys using the NEW passphrase - should SUCCEED
  1465  	returnNewPassphrase = true
  1466  	newKey, err = keys.GenerateEd25519Key()
  1467  	c.Assert(err, IsNil)
  1468  	newPrivateKey, err = newKey.MarshalPrivateKey()
  1469  	c.Assert(err, IsNil)
  1470  	c.Assert(store.SaveSigner("root", newKey), IsNil)
  1471  
  1472  	// 8. Verify again that the key entries are what we expect after decrypting them using the NEW passphrase
  1473  	assertKeys("root", true, []*data.PrivateKey{privateKey, newPrivateKey})
  1474  }
  1475  
  1476  func (rs *RepoSuite) TestManageMultipleTargets(c *C) {
  1477  	tmp := newTmpDir(c)
  1478  	local := FileSystemStore(tmp.path, nil)
  1479  	r, err := NewRepo(local)
  1480  	c.Assert(err, IsNil)
  1481  	// don't use consistent snapshots to make the checks simpler
  1482  	c.Assert(r.Init(false), IsNil)
  1483  	genKey(c, r, "root")
  1484  	genKey(c, r, "targets")
  1485  	genKey(c, r, "snapshot")
  1486  	genKey(c, r, "timestamp")
  1487  
  1488  	assertRepoTargets := func(paths ...string) {
  1489  		t, err := r.topLevelTargets()
  1490  		c.Assert(err, IsNil)
  1491  		for _, path := range paths {
  1492  			if _, ok := t.Targets[path]; !ok {
  1493  				c.Fatalf("missing target file: %s", path)
  1494  			}
  1495  		}
  1496  	}
  1497  
  1498  	// adding and committing multiple files moves correct targets from staged -> repository
  1499  	tmp.writeStagedTarget("foo.txt", "foo")
  1500  	tmp.writeStagedTarget("bar.txt", "bar")
  1501  	c.Assert(r.AddTargets([]string{"foo.txt", "bar.txt"}, nil), IsNil)
  1502  	c.Assert(r.Snapshot(), IsNil)
  1503  	c.Assert(r.Timestamp(), IsNil)
  1504  	c.Assert(r.Commit(), IsNil)
  1505  	assertRepoTargets("foo.txt", "bar.txt")
  1506  	tmp.assertExists("repository/targets/foo.txt")
  1507  	tmp.assertExists("repository/targets/bar.txt")
  1508  
  1509  	// adding all targets moves them all from staged -> repository
  1510  	count := 10
  1511  	files := make([]string, count)
  1512  	for i := 0; i < count; i++ {
  1513  		files[i] = fmt.Sprintf("file%d.txt", i)
  1514  		tmp.writeStagedTarget(files[i], "data")
  1515  	}
  1516  	c.Assert(r.AddTargets(nil, nil), IsNil)
  1517  	c.Assert(r.Snapshot(), IsNil)
  1518  	c.Assert(r.Timestamp(), IsNil)
  1519  	c.Assert(r.Commit(), IsNil)
  1520  	tmp.assertExists("repository/targets/foo.txt")
  1521  	tmp.assertExists("repository/targets/bar.txt")
  1522  	assertRepoTargets(files...)
  1523  	for _, file := range files {
  1524  		tmp.assertExists("repository/targets/" + file)
  1525  	}
  1526  	tmp.assertEmpty("staged/targets")
  1527  	tmp.assertEmpty("staged")
  1528  
  1529  	// removing all targets removes them from the repository and targets.json
  1530  	c.Assert(r.RemoveTargets(nil), IsNil)
  1531  	c.Assert(r.Snapshot(), IsNil)
  1532  	c.Assert(r.Timestamp(), IsNil)
  1533  	c.Assert(r.Commit(), IsNil)
  1534  	tmp.assertNotExist("repository/targets")
  1535  	t, err := r.topLevelTargets()
  1536  	c.Assert(err, IsNil)
  1537  	c.Assert(t.Targets, HasLen, 0)
  1538  }
  1539  
  1540  func (rs *RepoSuite) TestCustomTargetMetadata(c *C) {
  1541  	files := map[string][]byte{
  1542  		"foo.txt": []byte("foo"),
  1543  		"bar.txt": []byte("bar"),
  1544  		"baz.txt": []byte("baz"),
  1545  	}
  1546  	local := MemoryStore(make(map[string]json.RawMessage), files)
  1547  	r, err := NewRepo(local)
  1548  	c.Assert(err, IsNil)
  1549  
  1550  	generateAndAddPrivateKey(c, r, "targets")
  1551  
  1552  	custom := json.RawMessage(`{"foo":"bar"}`)
  1553  	assertCustomMeta := func(file string, custom *json.RawMessage) {
  1554  		t, err := r.topLevelTargets()
  1555  		c.Assert(err, IsNil)
  1556  		target, ok := t.Targets[file]
  1557  		if !ok {
  1558  			c.Fatalf("missing target file: %s", file)
  1559  		}
  1560  		c.Assert(target.Custom, DeepEquals, custom)
  1561  	}
  1562  
  1563  	// check custom metadata gets added to the target
  1564  	c.Assert(r.AddTarget("foo.txt", custom), IsNil)
  1565  	assertCustomMeta("foo.txt", &custom)
  1566  
  1567  	// check adding bar.txt with no metadata doesn't affect foo.txt
  1568  	c.Assert(r.AddTarget("bar.txt", nil), IsNil)
  1569  	assertCustomMeta("bar.txt", nil)
  1570  	assertCustomMeta("foo.txt", &custom)
  1571  
  1572  	// check adding all files with no metadata doesn't reset existing metadata
  1573  	c.Assert(r.AddTargets(nil, nil), IsNil)
  1574  	assertCustomMeta("baz.txt", nil)
  1575  	assertCustomMeta("bar.txt", nil)
  1576  	assertCustomMeta("foo.txt", &custom)
  1577  }
  1578  
  1579  func (rs *RepoSuite) TestUnknownKeyIDs(c *C) {
  1580  	// generate a repo
  1581  	local := MemoryStore(make(map[string]json.RawMessage), nil)
  1582  	r, err := NewRepo(local)
  1583  	c.Assert(err, IsNil)
  1584  
  1585  	genKey(c, r, "root")
  1586  	genKey(c, r, "targets")
  1587  	genKey(c, r, "snapshot")
  1588  	genKey(c, r, "timestamp")
  1589  
  1590  	// add a new key to the root metadata with an unknown key id.
  1591  	signer, err := keys.GenerateEd25519Key()
  1592  	c.Assert(err, IsNil)
  1593  
  1594  	root, err := r.root()
  1595  	c.Assert(err, IsNil)
  1596  	c.Assert(root.Version, Equals, int64(1))
  1597  
  1598  	root.Keys["unknown-key-id"] = signer.PublicData()
  1599  	r.setMeta("root.json", root)
  1600  
  1601  	// commit the metadata to the store.
  1602  	c.Assert(r.AddTargets([]string{}, nil), IsNil)
  1603  	c.Assert(r.Snapshot(), IsNil)
  1604  	c.Assert(r.Timestamp(), IsNil)
  1605  	c.Assert(r.Commit(), IsNil)
  1606  
  1607  	// validate that the unknown key id wasn't stripped when written to the
  1608  	// store.
  1609  	meta, err := local.GetMeta()
  1610  	c.Assert(err, IsNil)
  1611  
  1612  	rootJSON, ok := meta["root.json"]
  1613  	c.Assert(ok, Equals, true)
  1614  
  1615  	var signedRoot struct {
  1616  		Signed     data.Root        `json:"signed"`
  1617  		Signatures []data.Signature `json:"signatures"`
  1618  	}
  1619  	c.Assert(json.Unmarshal(rootJSON, &signedRoot), IsNil)
  1620  	c.Assert(signedRoot.Signed.Version, Equals, int64(1))
  1621  
  1622  	unknownKey, ok := signedRoot.Signed.Keys["unknown-key-id"]
  1623  	c.Assert(ok, Equals, true)
  1624  	c.Assert(unknownKey, DeepEquals, signer.PublicData())
  1625  
  1626  	// a new root should preserve the unknown key id.
  1627  	root, err = r.root()
  1628  	c.Assert(root, NotNil)
  1629  	c.Assert(err, IsNil)
  1630  
  1631  	genKey(c, r, "timestamp")
  1632  	c.Assert(r.Snapshot(), IsNil)
  1633  	c.Assert(r.Timestamp(), IsNil)
  1634  	c.Assert(r.Commit(), IsNil)
  1635  
  1636  	meta, err = local.GetMeta()
  1637  	c.Assert(err, IsNil)
  1638  
  1639  	rootJSON, ok = meta["root.json"]
  1640  	c.Assert(ok, Equals, true)
  1641  
  1642  	c.Assert(json.Unmarshal(rootJSON, &signedRoot), IsNil)
  1643  	c.Assert(signedRoot.Signed.Version, Equals, int64(2))
  1644  
  1645  	unknownKey, ok = signedRoot.Signed.Keys["unknown-key-id"]
  1646  	c.Assert(ok, Equals, true)
  1647  	c.Assert(unknownKey, DeepEquals, signer.PublicData())
  1648  }
  1649  
  1650  func (rs *RepoSuite) TestThreshold(c *C) {
  1651  	local := MemoryStore(make(map[string]json.RawMessage), nil)
  1652  	r, err := NewRepo(local)
  1653  	c.Assert(err, IsNil)
  1654  
  1655  	_, err = r.GetThreshold("root")
  1656  	c.Assert(err, DeepEquals, ErrInvalidRole{"root", "role missing from root metadata"})
  1657  	err = r.SetThreshold("root", 2)
  1658  	c.Assert(err, DeepEquals, ErrInvalidRole{"root", "role missing from root metadata"})
  1659  
  1660  	// Add one key to each role
  1661  	genKey(c, r, "root")
  1662  	genKey(c, r, "targets")
  1663  	genKey(c, r, "snapshot")
  1664  	genKey(c, r, "timestamp")
  1665  	t, err := r.GetThreshold("root")
  1666  	c.Assert(err, IsNil)
  1667  	c.Assert(t, Equals, 1)
  1668  
  1669  	_, err = r.GetThreshold("foo")
  1670  	c.Assert(err, DeepEquals, ErrInvalidRole{"foo", "only thresholds for top-level roles supported"})
  1671  	err = r.SetThreshold("foo", 2)
  1672  	c.Assert(err, DeepEquals, ErrInvalidRole{"foo", "only thresholds for top-level roles supported"})
  1673  
  1674  	// commit the metadata to the store.
  1675  	c.Assert(r.AddTargets([]string{}, nil), IsNil)
  1676  	c.Assert(r.Snapshot(), IsNil)
  1677  	c.Assert(r.Timestamp(), IsNil)
  1678  	c.Assert(r.Commit(), IsNil)
  1679  
  1680  	// Set a new threshold. Commit without threshold keys
  1681  	c.Assert(r.SetThreshold("root", 2), IsNil)
  1682  	t, err = r.GetThreshold("root")
  1683  	c.Assert(err, IsNil)
  1684  	c.Assert(t, Equals, 2)
  1685  	c.Assert(r.Commit(), DeepEquals, ErrNotEnoughKeys{"root", 1, 2})
  1686  
  1687  	// Add a second root key and try again
  1688  	genKey(c, r, "root")
  1689  	c.Assert(r.Sign("root.json"), IsNil)
  1690  	c.Assert(r.Snapshot(), IsNil)
  1691  	c.Assert(r.Timestamp(), IsNil)
  1692  	c.Assert(r.Commit(), IsNil)
  1693  
  1694  	// Check versions updated
  1695  	rootVersion, err := r.RootVersion()
  1696  	c.Assert(err, IsNil)
  1697  	c.Assert(rootVersion, Equals, int64(2))
  1698  
  1699  	targetsVersion, err := r.TargetsVersion()
  1700  	c.Assert(err, IsNil)
  1701  	c.Assert(targetsVersion, Equals, int64(1))
  1702  
  1703  	snapshotVersion, err := r.SnapshotVersion()
  1704  	c.Assert(err, IsNil)
  1705  	c.Assert(snapshotVersion, Equals, int64(2))
  1706  
  1707  	timestampVersion, err := r.TimestampVersion()
  1708  	c.Assert(err, IsNil)
  1709  	c.Assert(timestampVersion, Equals, int64(2))
  1710  }
  1711  
  1712  func (rs *RepoSuite) TestAddOrUpdateSignatures(c *C) {
  1713  	files := map[string][]byte{"foo.txt": []byte("foo")}
  1714  	local := MemoryStore(make(map[string]json.RawMessage), files)
  1715  	r, err := NewRepo(local)
  1716  	c.Assert(err, IsNil)
  1717  
  1718  	// don't use consistent snapshots to make the checks simpler
  1719  	c.Assert(r.Init(false), IsNil)
  1720  
  1721  	// generate root key offline and add as a verification key
  1722  	rootKey, err := keys.GenerateEd25519Key()
  1723  	c.Assert(err, IsNil)
  1724  	c.Assert(r.AddVerificationKey("root", rootKey.PublicData()), IsNil)
  1725  	targetsKey, err := keys.GenerateEd25519Key()
  1726  	c.Assert(err, IsNil)
  1727  	c.Assert(r.AddVerificationKey("targets", targetsKey.PublicData()), IsNil)
  1728  	snapshotKey, err := keys.GenerateEd25519Key()
  1729  	c.Assert(err, IsNil)
  1730  	c.Assert(r.AddVerificationKey("snapshot", snapshotKey.PublicData()), IsNil)
  1731  	timestampKey, err := keys.GenerateEd25519Key()
  1732  	c.Assert(err, IsNil)
  1733  	c.Assert(r.AddVerificationKey("timestamp", timestampKey.PublicData()), IsNil)
  1734  
  1735  	// generate signatures externally and append
  1736  	rootMeta, err := r.SignedMeta("root.json")
  1737  	c.Assert(err, IsNil)
  1738  	rootCanonical, err := cjson.EncodeCanonical(rootMeta.Signed)
  1739  	c.Assert(err, IsNil)
  1740  	rootSig, err := rootKey.SignMessage(rootCanonical)
  1741  	c.Assert(err, IsNil)
  1742  	for _, id := range rootKey.PublicData().IDs() {
  1743  		c.Assert(r.AddOrUpdateSignature("root.json", data.Signature{
  1744  			KeyID:     id,
  1745  			Signature: rootSig}), IsNil)
  1746  	}
  1747  
  1748  	// add targets and sign
  1749  	c.Assert(r.AddTarget("foo.txt", nil), IsNil)
  1750  	targetsMeta, err := r.SignedMeta("targets.json")
  1751  	c.Assert(err, IsNil)
  1752  	targetsCanonical, err := cjson.EncodeCanonical(targetsMeta.Signed)
  1753  	c.Assert(err, IsNil)
  1754  	targetsSig, err := targetsKey.SignMessage(targetsCanonical)
  1755  	c.Assert(err, IsNil)
  1756  	for _, id := range targetsKey.PublicData().IDs() {
  1757  		r.AddOrUpdateSignature("targets.json", data.Signature{
  1758  			KeyID:     id,
  1759  			Signature: targetsSig})
  1760  	}
  1761  
  1762  	// snapshot and timestamp
  1763  	c.Assert(r.Snapshot(), IsNil)
  1764  	snapshotMeta, err := r.SignedMeta("snapshot.json")
  1765  	c.Assert(err, IsNil)
  1766  	snapshotCanonical, err := cjson.EncodeCanonical(snapshotMeta.Signed)
  1767  	c.Assert(err, IsNil)
  1768  	snapshotSig, err := snapshotKey.SignMessage(snapshotCanonical)
  1769  	c.Assert(err, IsNil)
  1770  	for _, id := range snapshotKey.PublicData().IDs() {
  1771  		r.AddOrUpdateSignature("snapshot.json", data.Signature{
  1772  			KeyID:     id,
  1773  			Signature: snapshotSig})
  1774  	}
  1775  
  1776  	c.Assert(r.Timestamp(), IsNil)
  1777  	timestampMeta, err := r.SignedMeta("timestamp.json")
  1778  	c.Assert(err, IsNil)
  1779  	timestampCanonical, err := cjson.EncodeCanonical(timestampMeta.Signed)
  1780  	c.Assert(err, IsNil)
  1781  	timestampSig, err := timestampKey.SignMessage(timestampCanonical)
  1782  	c.Assert(err, IsNil)
  1783  	for _, id := range timestampKey.PublicData().IDs() {
  1784  		r.AddOrUpdateSignature("timestamp.json", data.Signature{
  1785  			KeyID:     id,
  1786  			Signature: timestampSig})
  1787  	}
  1788  
  1789  	// commit successfully!
  1790  	c.Assert(r.Commit(), IsNil)
  1791  }
  1792  
  1793  func (rs *RepoSuite) TestBadAddOrUpdateSignatures(c *C) {
  1794  	files := map[string][]byte{"foo.txt": []byte("foo")}
  1795  	local := MemoryStore(make(map[string]json.RawMessage), files)
  1796  	r, err := NewRepo(local)
  1797  	c.Assert(err, IsNil)
  1798  
  1799  	// don't use consistent snapshots to make the checks simpler
  1800  	c.Assert(r.Init(false), IsNil)
  1801  
  1802  	c.Assert(r.AddOrUpdateSignature("targets.json", data.Signature{
  1803  		KeyID:     "foo",
  1804  		Signature: nil}), Equals, ErrInvalidRole{"targets", "role is not in verifier DB"})
  1805  
  1806  	// generate root key offline and add as a verification key
  1807  	rootKey, err := keys.GenerateEd25519Key()
  1808  	c.Assert(err, IsNil)
  1809  	c.Assert(r.AddVerificationKey("root", rootKey.PublicData()), IsNil)
  1810  	targetsKey, err := keys.GenerateEd25519Key()
  1811  	c.Assert(err, IsNil)
  1812  	c.Assert(r.AddVerificationKey("targets", targetsKey.PublicData()), IsNil)
  1813  	snapshotKey, err := keys.GenerateEd25519Key()
  1814  	c.Assert(err, IsNil)
  1815  	c.Assert(r.AddVerificationKey("snapshot", snapshotKey.PublicData()), IsNil)
  1816  	timestampKey, err := keys.GenerateEd25519Key()
  1817  	c.Assert(err, IsNil)
  1818  	c.Assert(r.AddVerificationKey("timestamp", timestampKey.PublicData()), IsNil)
  1819  
  1820  	// attempt to sign `root`, rather than `root.json`
  1821  	for _, id := range rootKey.PublicData().IDs() {
  1822  		c.Assert(r.AddOrUpdateSignature("root", data.Signature{
  1823  			KeyID:     id,
  1824  			Signature: nil}), Equals, ErrMissingMetadata{"root"})
  1825  	}
  1826  
  1827  	// add a signature with a bad role
  1828  	rootMeta, err := r.SignedMeta("root.json")
  1829  	c.Assert(err, IsNil)
  1830  	rootCanonical, err := cjson.EncodeCanonical(rootMeta.Signed)
  1831  	c.Assert(err, IsNil)
  1832  	rootSig, err := rootKey.Sign(rand.Reader, rootCanonical, crypto.Hash(0))
  1833  	c.Assert(err, IsNil)
  1834  	for _, id := range rootKey.PublicData().IDs() {
  1835  		c.Assert(r.AddOrUpdateSignature("invalid_root.json", data.Signature{
  1836  			KeyID:     id,
  1837  			Signature: rootSig}), Equals, ErrInvalidRole{"invalid_root", "no trusted keys for role"})
  1838  	}
  1839  
  1840  	// add a root signature with an key ID that is for the targets role
  1841  	for _, id := range targetsKey.PublicData().IDs() {
  1842  		c.Assert(r.AddOrUpdateSignature("root.json", data.Signature{
  1843  			KeyID:     id,
  1844  			Signature: rootSig}), Equals, verify.ErrInvalidKey)
  1845  	}
  1846  
  1847  	// attempt to add a bad signature to root
  1848  	badSig, err := rootKey.Sign(rand.Reader, []byte(""), crypto.Hash(0))
  1849  	c.Assert(err, IsNil)
  1850  	for _, id := range rootKey.PublicData().IDs() {
  1851  		c.Assert(r.AddOrUpdateSignature("root.json", data.Signature{
  1852  			KeyID:     id,
  1853  			Signature: badSig}), Equals, verify.ErrInvalid)
  1854  	}
  1855  
  1856  	// add the correct root signature
  1857  	for _, id := range rootKey.PublicData().IDs() {
  1858  		c.Assert(r.AddOrUpdateSignature("root.json", data.Signature{
  1859  			KeyID:     id,
  1860  			Signature: rootSig}), IsNil)
  1861  	}
  1862  	checkSigIDs := func(role string) {
  1863  		s, err := r.SignedMeta(role)
  1864  		c.Assert(err, IsNil)
  1865  		db, err := r.topLevelKeysDB()
  1866  		c.Assert(err, IsNil)
  1867  		// keys is a map of key IDs.
  1868  		keys := db.GetRole(strings.TrimSuffix(role, ".json")).KeyIDs
  1869  		c.Assert(s.Signatures, HasLen, len(keys))
  1870  		// If the lengths are equal, and each signature key ID appears
  1871  		// in the role keys, they Sig IDs are equal to keyIDs.
  1872  		for _, sig := range s.Signatures {
  1873  			if _, ok := keys[sig.KeyID]; !ok {
  1874  				c.Fatal("missing key ID in signatures")
  1875  			}
  1876  		}
  1877  	}
  1878  	checkSigIDs("root.json")
  1879  
  1880  	// re-adding should not duplicate. this is checked by verifying
  1881  	// signature key IDs match with the map of role key IDs.
  1882  	for _, id := range rootKey.PublicData().IDs() {
  1883  		c.Assert(r.AddOrUpdateSignature("root.json", data.Signature{
  1884  			KeyID:     id,
  1885  			Signature: rootSig}), IsNil)
  1886  	}
  1887  	checkSigIDs("root.json")
  1888  }
  1889  
  1890  func (rs *RepoSuite) TestSignDigest(c *C) {
  1891  	files := map[string][]byte{"foo.txt": []byte("foo")}
  1892  	local := MemoryStore(make(map[string]json.RawMessage), files)
  1893  	r, err := NewRepo(local)
  1894  	c.Assert(err, IsNil)
  1895  
  1896  	genKey(c, r, "root")
  1897  	genKey(c, r, "targets")
  1898  	genKey(c, r, "snapshot")
  1899  	genKey(c, r, "timestamp")
  1900  
  1901  	digest := "sha256:bc11b176a293bb341a0f2d0d226f52e7fcebd186a7c4dfca5fc64f305f06b94c"
  1902  	hash := "bc11b176a293bb341a0f2d0d226f52e7fcebd186a7c4dfca5fc64f305f06b94c"
  1903  	size := int64(42)
  1904  
  1905  	c.Assert(r.AddTargetsWithDigest(hash, "sha256", size, digest, nil), IsNil)
  1906  	c.Assert(r.Snapshot(), IsNil)
  1907  	c.Assert(r.Timestamp(), IsNil)
  1908  	c.Assert(r.Commit(), IsNil)
  1909  
  1910  	digest_bytes, err := hex.DecodeString("bc11b176a293bb341a0f2d0d226f52e7fcebd186a7c4dfca5fc64f305f06b94c")
  1911  	hex_digest_bytes := data.HexBytes(digest_bytes)
  1912  	c.Assert(err, IsNil)
  1913  
  1914  	targets, err := r.topLevelTargets()
  1915  	c.Assert(err, IsNil)
  1916  	c.Assert(targets.Targets["sha256:bc11b176a293bb341a0f2d0d226f52e7fcebd186a7c4dfca5fc64f305f06b94c"].FileMeta.Length, Equals, size)
  1917  	c.Assert(targets.Targets["sha256:bc11b176a293bb341a0f2d0d226f52e7fcebd186a7c4dfca5fc64f305f06b94c"].FileMeta.Hashes["sha256"], DeepEquals, hex_digest_bytes)
  1918  }
  1919  
  1920  func concat(ss ...[]string) []string {
  1921  	ret := []string{}
  1922  	for _, s := range ss {
  1923  		ret = append(ret, s...)
  1924  	}
  1925  	return ret
  1926  }
  1927  
  1928  func checkSigKeyIDs(c *C, local LocalStore, fileToKeyIDs map[string][]string) {
  1929  	metas, err := local.GetMeta()
  1930  	c.Assert(err, IsNil)
  1931  
  1932  	for f, keyIDs := range fileToKeyIDs {
  1933  		meta, ok := metas[f]
  1934  		c.Assert(ok, Equals, true, Commentf("meta file: %v", f))
  1935  
  1936  		s := &data.Signed{}
  1937  		err = json.Unmarshal(meta, s)
  1938  		c.Assert(err, IsNil)
  1939  
  1940  		gotKeyIDs := []string{}
  1941  		for _, sig := range s.Signatures {
  1942  			gotKeyIDs = append(gotKeyIDs, sig.KeyID)
  1943  		}
  1944  		gotKeyIDs = sets.DeduplicateStrings(gotKeyIDs)
  1945  		sort.Strings(gotKeyIDs)
  1946  
  1947  		sort.Strings(keyIDs)
  1948  		c.Assert(gotKeyIDs, DeepEquals, keyIDs)
  1949  	}
  1950  }
  1951  
  1952  func (rs *RepoSuite) TestDelegations(c *C) {
  1953  	tmp := newTmpDir(c)
  1954  	local := FileSystemStore(tmp.path, nil)
  1955  	r, err := NewRepo(local)
  1956  	c.Assert(err, IsNil)
  1957  
  1958  	// Add one key to each role
  1959  	genKey(c, r, "root")
  1960  	targetsKeyIDs := genKey(c, r, "targets")
  1961  	genKey(c, r, "snapshot")
  1962  	genKey(c, r, "timestamp")
  1963  
  1964  	// commit the metadata to the store.
  1965  	c.Assert(r.AddTargets([]string{}, nil), IsNil)
  1966  	c.Assert(r.Snapshot(), IsNil)
  1967  	c.Assert(r.Timestamp(), IsNil)
  1968  	c.Assert(r.Commit(), IsNil)
  1969  
  1970  	snapshot, err := r.snapshot()
  1971  	c.Assert(err, IsNil)
  1972  	c.Assert(snapshot.Meta, HasLen, 1)
  1973  	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(1))
  1974  
  1975  	checkSigKeyIDs(c, local, map[string][]string{
  1976  		"1.targets.json": targetsKeyIDs,
  1977  	})
  1978  
  1979  	saveNewKey := func(role string) keys.Signer {
  1980  		key, err := keys.GenerateEd25519Key()
  1981  		c.Assert(err, IsNil)
  1982  
  1983  		err = local.SaveSigner(role, key)
  1984  		c.Assert(err, IsNil)
  1985  
  1986  		return key
  1987  	}
  1988  
  1989  	// Delegate from targets -> role1 for A/*, B/* with one key, threshold 1.
  1990  	role1ABKey := saveNewKey("role1")
  1991  	role1AB := data.DelegatedRole{
  1992  		Name:      "role1",
  1993  		KeyIDs:    role1ABKey.PublicData().IDs(),
  1994  		Paths:     []string{"A/*", "B/*"},
  1995  		Threshold: 1,
  1996  	}
  1997  	err = r.AddDelegatedRole("targets", role1AB, []*data.PublicKey{
  1998  		role1ABKey.PublicData(),
  1999  	})
  2000  	c.Assert(err, IsNil)
  2001  
  2002  	// Adding duplicate delegation should return an error.
  2003  	err = r.AddDelegatedRole("targets", role1AB, []*data.PublicKey{
  2004  		role1ABKey.PublicData(),
  2005  	})
  2006  	c.Assert(err, NotNil)
  2007  
  2008  	// Delegate from targets -> role2 for C/*, D/* with three key, threshold 2.
  2009  	role2CDKey1 := saveNewKey("role2")
  2010  	role2CDKey2 := saveNewKey("role2")
  2011  	role2CDKey3 := saveNewKey("role2")
  2012  	role2CD := data.DelegatedRole{
  2013  		Name: "role2",
  2014  		KeyIDs: concat(
  2015  			role2CDKey1.PublicData().IDs(),
  2016  			role2CDKey2.PublicData().IDs(),
  2017  			role2CDKey3.PublicData().IDs(),
  2018  		),
  2019  		Paths:     []string{"C/*", "D/*"},
  2020  		Threshold: 2,
  2021  	}
  2022  	err = r.AddDelegatedRole("targets", role2CD, []*data.PublicKey{
  2023  		role2CDKey1.PublicData(),
  2024  		role2CDKey2.PublicData(),
  2025  		role2CDKey3.PublicData(),
  2026  	})
  2027  	c.Assert(err, IsNil)
  2028  
  2029  	// Delegate from role1 -> role2 for A/allium.txt with one key, threshold 1.
  2030  	role1To2Key := saveNewKey("role2")
  2031  	role1To2 := data.DelegatedRole{
  2032  		Name:        "role2",
  2033  		KeyIDs:      role1To2Key.PublicData().IDs(),
  2034  		Paths:       []string{"A/allium.txt"},
  2035  		Threshold:   1,
  2036  		Terminating: true,
  2037  	}
  2038  	err = r.AddDelegatedRole("role1", role1To2, []*data.PublicKey{
  2039  		role1To2Key.PublicData(),
  2040  	})
  2041  	c.Assert(err, IsNil)
  2042  
  2043  	checkDelegations := func(delegator string, delegatedRoles ...data.DelegatedRole) {
  2044  		t, err := r.targets(delegator)
  2045  		c.Assert(err, IsNil)
  2046  
  2047  		// Check if there are no delegations.
  2048  		if t.Delegations == nil {
  2049  			if delegatedRoles != nil {
  2050  				c.Fatal("expected delegated roles on delegator")
  2051  			}
  2052  			return
  2053  		}
  2054  
  2055  		// Check that delegated roles are copied verbatim.
  2056  		c.Assert(t.Delegations.Roles, DeepEquals, delegatedRoles)
  2057  
  2058  		// Check that public keys match key IDs in roles.
  2059  		expectedKeyIDs := []string{}
  2060  		for _, dr := range delegatedRoles {
  2061  			expectedKeyIDs = append(expectedKeyIDs, dr.KeyIDs...)
  2062  		}
  2063  		expectedKeyIDs = sets.DeduplicateStrings(expectedKeyIDs)
  2064  		sort.Strings(expectedKeyIDs)
  2065  
  2066  		gotKeyIDs := []string{}
  2067  		for _, k := range t.Delegations.Keys {
  2068  			gotKeyIDs = append(gotKeyIDs, k.IDs()...)
  2069  		}
  2070  		gotKeyIDs = sets.DeduplicateStrings(gotKeyIDs)
  2071  		sort.Strings(gotKeyIDs)
  2072  
  2073  		c.Assert(gotKeyIDs, DeepEquals, expectedKeyIDs)
  2074  	}
  2075  
  2076  	checkDelegations("targets", role1AB, role2CD)
  2077  	checkDelegations("role1", role1To2)
  2078  
  2079  	c.Assert(r.Snapshot(), IsNil)
  2080  	c.Assert(r.Timestamp(), IsNil)
  2081  	c.Assert(r.Commit(), IsNil)
  2082  
  2083  	snapshot, err = r.snapshot()
  2084  	c.Assert(err, IsNil)
  2085  	c.Assert(snapshot.Meta, HasLen, 3)
  2086  	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(2))
  2087  	c.Assert(snapshot.Meta["role1.json"].Version, Equals, int64(1))
  2088  	c.Assert(snapshot.Meta["role2.json"].Version, Equals, int64(1))
  2089  
  2090  	checkSigKeyIDs(c, local, map[string][]string{
  2091  		"2.targets.json": targetsKeyIDs,
  2092  		"1.role1.json":   role1ABKey.PublicData().IDs(),
  2093  		"1.role2.json": concat(
  2094  			role2CDKey1.PublicData().IDs(),
  2095  			role2CDKey2.PublicData().IDs(),
  2096  			role2CDKey3.PublicData().IDs(),
  2097  			role1To2Key.PublicData().IDs(),
  2098  		),
  2099  	})
  2100  
  2101  	// Add a variety of targets.
  2102  	files := map[string]string{
  2103  		// targets.json
  2104  		"potato.txt": "potatoes can be starchy or waxy",
  2105  		// role1.json
  2106  		"A/apple.txt":  "apples are sometimes red",
  2107  		"B/banana.txt": "bananas are yellow and sometimes brown",
  2108  		// role2.json
  2109  		"C/clementine.txt": "clementines are a citrus fruit",
  2110  		"D/durian.txt":     "durians are spiky",
  2111  		"A/allium.txt":     "alliums include garlic and leeks",
  2112  	}
  2113  	for name, content := range files {
  2114  		tmp.writeStagedTarget(name, content)
  2115  		c.Assert(r.AddTarget(name, nil), IsNil)
  2116  	}
  2117  
  2118  	c.Assert(r.Snapshot(), IsNil)
  2119  	c.Assert(r.Timestamp(), IsNil)
  2120  	c.Assert(r.Commit(), IsNil)
  2121  
  2122  	snapshot, err = r.snapshot()
  2123  	c.Assert(err, IsNil)
  2124  	c.Assert(snapshot.Meta, HasLen, 3)
  2125  	// All roles should have new targets.
  2126  	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(3))
  2127  	c.Assert(snapshot.Meta["role1.json"].Version, Equals, int64(2))
  2128  	c.Assert(snapshot.Meta["role2.json"].Version, Equals, int64(2))
  2129  
  2130  	checkSigKeyIDs(c, local, map[string][]string{
  2131  		"3.targets.json": targetsKeyIDs,
  2132  		"2.role1.json":   role1ABKey.PublicData().IDs(),
  2133  		"2.role2.json": concat(
  2134  			role2CDKey1.PublicData().IDs(),
  2135  			role2CDKey2.PublicData().IDs(),
  2136  			role2CDKey3.PublicData().IDs(),
  2137  			role1To2Key.PublicData().IDs(),
  2138  		),
  2139  	})
  2140  
  2141  	// Check that the given targets role has signed for the given filenames, with
  2142  	// the correct file metadata.
  2143  	checkTargets := func(role string, filenames ...string) {
  2144  		t, err := r.targets(role)
  2145  		c.Assert(err, IsNil)
  2146  		c.Assert(t.Targets, HasLen, len(filenames))
  2147  
  2148  		for _, fn := range filenames {
  2149  			content := files[fn]
  2150  
  2151  			fm, err := util.GenerateTargetFileMeta(strings.NewReader(content))
  2152  			c.Assert(err, IsNil)
  2153  
  2154  			c.Assert(util.TargetFileMetaEqual(t.Targets[fn], fm), IsNil)
  2155  		}
  2156  	}
  2157  
  2158  	checkTargets("targets", "potato.txt")
  2159  	checkTargets("role1", "A/apple.txt", "B/banana.txt")
  2160  	checkTargets("role2", "C/clementine.txt", "D/durian.txt", "A/allium.txt")
  2161  
  2162  	// Test AddTargetToPreferredRole.
  2163  	// role2 is the default signer for A/allium.txt, but role1 is also eligible
  2164  	// for A/*.txt according to the delegation from the top-level targets role.
  2165  	c.Assert(r.RemoveTarget("A/allium.txt"), IsNil)
  2166  	tmp.writeStagedTarget("A/allium.txt", files["A/allium.txt"])
  2167  	c.Assert(r.AddTargetToPreferredRole("A/allium.txt", nil, "role1"), IsNil)
  2168  
  2169  	c.Assert(r.Snapshot(), IsNil)
  2170  	c.Assert(r.Timestamp(), IsNil)
  2171  	c.Assert(r.Commit(), IsNil)
  2172  
  2173  	snapshot, err = r.snapshot()
  2174  	c.Assert(err, IsNil)
  2175  	c.Assert(snapshot.Meta, HasLen, 3)
  2176  	// Only role1 and role2 should have bumped versions.
  2177  	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(3))
  2178  	c.Assert(snapshot.Meta["role1.json"].Version, Equals, int64(3))
  2179  	c.Assert(snapshot.Meta["role2.json"].Version, Equals, int64(3))
  2180  
  2181  	checkSigKeyIDs(c, local, map[string][]string{
  2182  		"3.targets.json": targetsKeyIDs,
  2183  		"3.role1.json":   role1ABKey.PublicData().IDs(),
  2184  		"3.role2.json": concat(
  2185  			role2CDKey1.PublicData().IDs(),
  2186  			role2CDKey2.PublicData().IDs(),
  2187  			role2CDKey3.PublicData().IDs(),
  2188  			role1To2Key.PublicData().IDs(),
  2189  		),
  2190  	})
  2191  
  2192  	// role1 now signs A/allium.txt.
  2193  	checkTargets("targets", "potato.txt")
  2194  	checkTargets("role1", "A/apple.txt", "B/banana.txt", "A/allium.txt")
  2195  	checkTargets("role2", "C/clementine.txt", "D/durian.txt")
  2196  
  2197  	// Remove the delegation from role1 to role2.
  2198  	c.Assert(r.ResetTargetsDelegations("role1"), IsNil)
  2199  	checkDelegations("targets", role1AB, role2CD)
  2200  	checkDelegations("role1")
  2201  
  2202  	// Try to sign A/allium.txt with role2.
  2203  	// It should fail since we removed the role1 -> role2 delegation.
  2204  	c.Assert(r.RemoveTarget("A/allium.txt"), IsNil)
  2205  	tmp.writeStagedTarget("A/allium.txt", files["A/allium.txt"])
  2206  	c.Assert(r.AddTargetToPreferredRole("A/allium.txt", nil, "role2"), Equals, ErrNoDelegatedTarget{Path: "A/allium.txt"})
  2207  
  2208  	// Try to sign A/allium.txt with the default role (role1).
  2209  	c.Assert(r.AddTarget("A/allium.txt", nil), IsNil)
  2210  
  2211  	c.Assert(r.Snapshot(), IsNil)
  2212  	c.Assert(r.Timestamp(), IsNil)
  2213  	c.Assert(r.Commit(), IsNil)
  2214  
  2215  	snapshot, err = r.snapshot()
  2216  	c.Assert(err, IsNil)
  2217  	c.Assert(snapshot.Meta, HasLen, 3)
  2218  	// Only role1 should have a bumped version.
  2219  	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(3))
  2220  	c.Assert(snapshot.Meta["role1.json"].Version, Equals, int64(4))
  2221  	c.Assert(snapshot.Meta["role2.json"].Version, Equals, int64(3))
  2222  
  2223  	checkSigKeyIDs(c, local, map[string][]string{
  2224  		"3.targets.json": targetsKeyIDs,
  2225  		"4.role1.json":   role1ABKey.PublicData().IDs(),
  2226  		"3.role2.json": concat(
  2227  			// Metadata (and therefore signers) for role2.json shouldn't have
  2228  			// changed, even though we revoked role1To2Key. Clients verify the
  2229  			// signature using keys specified by 4.role1.json, so role1To2Key
  2230  			// shouldn't contribute to the threshold.
  2231  			role2CDKey1.PublicData().IDs(),
  2232  			role2CDKey2.PublicData().IDs(),
  2233  			role2CDKey3.PublicData().IDs(),
  2234  			role1To2Key.PublicData().IDs(),
  2235  		),
  2236  	})
  2237  
  2238  	// Re-sign target signed by role2 to test that role1To2Key is not used going
  2239  	// forward.
  2240  	c.Assert(r.RemoveTarget("C/clementine.txt"), IsNil)
  2241  	tmp.writeStagedTarget("C/clementine.txt", files["C/clementine.txt"])
  2242  	c.Assert(r.AddTarget("C/clementine.txt", nil), IsNil)
  2243  
  2244  	c.Assert(r.Snapshot(), IsNil)
  2245  	c.Assert(r.Timestamp(), IsNil)
  2246  	c.Assert(r.Commit(), IsNil)
  2247  
  2248  	snapshot, err = r.snapshot()
  2249  	c.Assert(err, IsNil)
  2250  	c.Assert(snapshot.Meta, HasLen, 3)
  2251  	// Only role2 should have a bumped version.
  2252  	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(3))
  2253  	c.Assert(snapshot.Meta["role1.json"].Version, Equals, int64(4))
  2254  	c.Assert(snapshot.Meta["role2.json"].Version, Equals, int64(4))
  2255  
  2256  	checkSigKeyIDs(c, local, map[string][]string{
  2257  		"3.targets.json": targetsKeyIDs,
  2258  		"4.role1.json":   role1ABKey.PublicData().IDs(),
  2259  		"4.role2.json": concat(
  2260  			role2CDKey1.PublicData().IDs(),
  2261  			role2CDKey2.PublicData().IDs(),
  2262  			role2CDKey3.PublicData().IDs(),
  2263  			// Note that role1To2Key no longer signs since the role1 -> role2
  2264  			// delegation was removed.
  2265  		),
  2266  	})
  2267  
  2268  	// Targets should still be signed by the same roles.
  2269  	checkTargets("targets", "potato.txt")
  2270  	checkTargets("role1", "A/apple.txt", "B/banana.txt", "A/allium.txt")
  2271  	checkTargets("role2", "C/clementine.txt", "D/durian.txt")
  2272  
  2273  	// Add back the role1 -> role2 delegation, and verify that it doesn't change
  2274  	// existing targets in role2.json.
  2275  	err = r.AddDelegatedRole("role1", role1To2, []*data.PublicKey{
  2276  		role1To2Key.PublicData(),
  2277  	})
  2278  	c.Assert(err, IsNil)
  2279  	c.Assert(r.Snapshot(), IsNil)
  2280  	c.Assert(r.Timestamp(), IsNil)
  2281  	c.Assert(r.Commit(), IsNil)
  2282  
  2283  	snapshot, err = r.snapshot()
  2284  	c.Assert(err, IsNil)
  2285  	c.Assert(snapshot.Meta, HasLen, 3)
  2286  	// Both role1 and role2 should have a bumped version.
  2287  	// role1 is bumped because the delegations changed.
  2288  	// role2 is only bumped because its expiration is bumped.
  2289  	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(3))
  2290  	c.Assert(snapshot.Meta["role1.json"].Version, Equals, int64(5))
  2291  	c.Assert(snapshot.Meta["role2.json"].Version, Equals, int64(5))
  2292  
  2293  	checkTargets("targets", "potato.txt")
  2294  	checkTargets("role1", "A/apple.txt", "B/banana.txt", "A/allium.txt")
  2295  	checkTargets("role2", "C/clementine.txt", "D/durian.txt")
  2296  }
  2297  
  2298  func (rs *RepoSuite) TestHashBinDelegations(c *C) {
  2299  	tmp := newTmpDir(c)
  2300  	local := FileSystemStore(tmp.path, nil)
  2301  	r, err := NewRepo(local)
  2302  	c.Assert(err, IsNil)
  2303  
  2304  	// Add one key to each role
  2305  	genKey(c, r, "root")
  2306  	targetsKeyIDs := genKey(c, r, "targets")
  2307  	genKey(c, r, "snapshot")
  2308  	genKey(c, r, "timestamp")
  2309  
  2310  	hb, err := targets.NewHashBins("bins_", 3)
  2311  	if err != nil {
  2312  		c.Assert(err, IsNil)
  2313  	}
  2314  
  2315  	// Generate key for the intermediate bins role.
  2316  	binsKey, err := keys.GenerateEd25519Key()
  2317  	c.Assert(err, IsNil)
  2318  	err = local.SaveSigner("bins", binsKey)
  2319  	c.Assert(err, IsNil)
  2320  
  2321  	// Generate key for the leaf bins role.
  2322  	leafKey, err := keys.GenerateEd25519Key()
  2323  	c.Assert(err, IsNil)
  2324  	for i := uint64(0); i < hb.NumBins(); i++ {
  2325  		b := hb.GetBin(i)
  2326  		err = local.SaveSigner(b.RoleName(), leafKey)
  2327  		if err != nil {
  2328  			c.Assert(err, IsNil)
  2329  		}
  2330  	}
  2331  
  2332  	err = r.AddDelegatedRole("targets", data.DelegatedRole{
  2333  		Name:      "bins",
  2334  		KeyIDs:    binsKey.PublicData().IDs(),
  2335  		Paths:     []string{"*.txt"},
  2336  		Threshold: 1,
  2337  	}, []*data.PublicKey{
  2338  		binsKey.PublicData(),
  2339  	})
  2340  	c.Assert(err, IsNil)
  2341  
  2342  	err = r.AddDelegatedRolesForPathHashBins("bins", hb, []*data.PublicKey{leafKey.PublicData()}, 1)
  2343  	c.Assert(err, IsNil)
  2344  	targets, err := r.targets("bins")
  2345  	c.Assert(err, IsNil)
  2346  	c.Assert(targets.Delegations.Roles, HasLen, 8)
  2347  
  2348  	c.Assert(r.Snapshot(), IsNil)
  2349  	c.Assert(r.Timestamp(), IsNil)
  2350  	c.Assert(r.Commit(), IsNil)
  2351  
  2352  	tmp.writeStagedTarget("foo.txt", "foo")
  2353  	err = r.AddTarget("foo.txt", nil)
  2354  	c.Assert(err, IsNil)
  2355  
  2356  	c.Assert(r.Snapshot(), IsNil)
  2357  	c.Assert(r.Timestamp(), IsNil)
  2358  	c.Assert(r.Commit(), IsNil)
  2359  
  2360  	snapshot, err := r.snapshot()
  2361  	c.Assert(err, IsNil)
  2362  	// 1 targets.json, 1 bins.json, 8 bins_*.json.
  2363  	c.Assert(snapshot.Meta, HasLen, 10)
  2364  	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(1))
  2365  	c.Assert(snapshot.Meta["bins.json"].Version, Equals, int64(1))
  2366  	c.Assert(snapshot.Meta["bins_0-1.json"].Version, Equals, int64(1))
  2367  	c.Assert(snapshot.Meta["bins_2-3.json"].Version, Equals, int64(1))
  2368  	c.Assert(snapshot.Meta["bins_4-5.json"].Version, Equals, int64(1))
  2369  	c.Assert(snapshot.Meta["bins_6-7.json"].Version, Equals, int64(1))
  2370  	c.Assert(snapshot.Meta["bins_8-9.json"].Version, Equals, int64(1))
  2371  	c.Assert(snapshot.Meta["bins_a-b.json"].Version, Equals, int64(1))
  2372  	c.Assert(snapshot.Meta["bins_c-d.json"].Version, Equals, int64(2))
  2373  	c.Assert(snapshot.Meta["bins_e-f.json"].Version, Equals, int64(1))
  2374  
  2375  	targets, err = r.targets("bins_c-d")
  2376  	c.Assert(err, IsNil)
  2377  	c.Assert(targets.Targets, HasLen, 1)
  2378  
  2379  	checkSigKeyIDs(c, local, map[string][]string{
  2380  		"targets.json":    targetsKeyIDs,
  2381  		"1.bins.json":     binsKey.PublicData().IDs(),
  2382  		"1.bins_0-1.json": leafKey.PublicData().IDs(),
  2383  		"1.bins_2-3.json": leafKey.PublicData().IDs(),
  2384  		"1.bins_4-5.json": leafKey.PublicData().IDs(),
  2385  		"1.bins_6-7.json": leafKey.PublicData().IDs(),
  2386  		"1.bins_8-9.json": leafKey.PublicData().IDs(),
  2387  		"1.bins_a-b.json": leafKey.PublicData().IDs(),
  2388  		"1.bins_c-d.json": leafKey.PublicData().IDs(),
  2389  		"2.bins_c-d.json": leafKey.PublicData().IDs(),
  2390  		"1.bins_e-f.json": leafKey.PublicData().IDs(),
  2391  	})
  2392  }
  2393  
  2394  func (rs *RepoSuite) TestResetTargetsDelegationsWithExpires(c *C) {
  2395  	tmp := newTmpDir(c)
  2396  	local := FileSystemStore(tmp.path, nil)
  2397  	r, err := NewRepo(local)
  2398  	c.Assert(err, IsNil)
  2399  
  2400  	// Add one key to each role
  2401  	genKey(c, r, "root")
  2402  	targetsKeyIDs := genKey(c, r, "targets")
  2403  	genKey(c, r, "snapshot")
  2404  	genKey(c, r, "timestamp")
  2405  
  2406  	// commit the metadata to the store.
  2407  	c.Assert(r.AddTargets([]string{}, nil), IsNil)
  2408  	c.Assert(r.Snapshot(), IsNil)
  2409  	c.Assert(r.Timestamp(), IsNil)
  2410  	c.Assert(r.Commit(), IsNil)
  2411  
  2412  	snapshot, err := r.snapshot()
  2413  	c.Assert(err, IsNil)
  2414  	c.Assert(snapshot.Meta, HasLen, 1)
  2415  	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(1))
  2416  
  2417  	checkSigKeyIDs(c, local, map[string][]string{
  2418  		"1.targets.json": targetsKeyIDs,
  2419  	})
  2420  
  2421  	role1Key, err := keys.GenerateEd25519Key()
  2422  	c.Assert(err, IsNil)
  2423  
  2424  	err = local.SaveSigner("role1", role1Key)
  2425  	c.Assert(err, IsNil)
  2426  
  2427  	// Delegate from targets -> role1 for A/*, B/* with one key, threshold 1.
  2428  	role1 := data.DelegatedRole{
  2429  		Name:      "role1",
  2430  		KeyIDs:    role1Key.PublicData().IDs(),
  2431  		Paths:     []string{"A/*", "B/*"},
  2432  		Threshold: 1,
  2433  	}
  2434  	err = r.AddDelegatedRole("targets", role1, []*data.PublicKey{
  2435  		role1Key.PublicData(),
  2436  	})
  2437  	c.Assert(err, IsNil)
  2438  
  2439  	c.Assert(r.Snapshot(), IsNil)
  2440  	c.Assert(r.Timestamp(), IsNil)
  2441  	c.Assert(r.Commit(), IsNil)
  2442  
  2443  	snapshot, err = r.snapshot()
  2444  	c.Assert(err, IsNil)
  2445  	c.Assert(snapshot.Meta, HasLen, 2)
  2446  	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(2))
  2447  	c.Assert(snapshot.Meta["role1.json"].Version, Equals, int64(1))
  2448  
  2449  	checkSigKeyIDs(c, local, map[string][]string{
  2450  		"1.targets.json": targetsKeyIDs,
  2451  		"targets.json":   targetsKeyIDs,
  2452  		"1.role1.json":   role1Key.PublicData().IDs(),
  2453  		"role1.json":     role1Key.PublicData().IDs(),
  2454  	})
  2455  
  2456  	c.Assert(r.ResetTargetsDelegations("targets"), IsNil)
  2457  	c.Assert(r.Snapshot(), IsNil)
  2458  	c.Assert(r.Timestamp(), IsNil)
  2459  	c.Assert(r.Commit(), IsNil)
  2460  
  2461  	snapshot, err = r.snapshot()
  2462  	c.Assert(err, IsNil)
  2463  	c.Assert(snapshot.Meta, HasLen, 2)
  2464  	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(3))
  2465  	c.Assert(snapshot.Meta["role1.json"].Version, Equals, int64(1))
  2466  
  2467  	checkSigKeyIDs(c, local, map[string][]string{
  2468  		"2.targets.json": targetsKeyIDs,
  2469  		"targets.json":   targetsKeyIDs,
  2470  		"1.role1.json":   role1Key.PublicData().IDs(),
  2471  		"role1.json":     role1Key.PublicData().IDs(),
  2472  	})
  2473  }
  2474  
  2475  func (rs *RepoSuite) TestSignWithDelegations(c *C) {
  2476  	tmp := newTmpDir(c)
  2477  	local := FileSystemStore(tmp.path, nil)
  2478  	r, err := NewRepo(local)
  2479  	c.Assert(err, IsNil)
  2480  
  2481  	// Add one key to each role
  2482  	genKey(c, r, "root")
  2483  	genKey(c, r, "targets")
  2484  	genKey(c, r, "snapshot")
  2485  	genKey(c, r, "timestamp")
  2486  
  2487  	role1Key, err := keys.GenerateEd25519Key()
  2488  	c.Assert(err, IsNil)
  2489  
  2490  	role1 := data.DelegatedRole{
  2491  		Name:      "role1",
  2492  		KeyIDs:    role1Key.PublicData().IDs(),
  2493  		Paths:     []string{"A/*", "B/*"},
  2494  		Threshold: 1,
  2495  	}
  2496  	err = r.AddDelegatedRole("targets", role1, []*data.PublicKey{
  2497  		role1Key.PublicData(),
  2498  	})
  2499  	c.Assert(err, IsNil)
  2500  
  2501  	// targets.json should be signed, but role1.json is not signed because there
  2502  	// is no key in the local store.
  2503  	m, err := local.GetMeta()
  2504  	c.Assert(err, IsNil)
  2505  	targetsMeta := &data.Signed{}
  2506  	c.Assert(json.Unmarshal(m["targets.json"], targetsMeta), IsNil)
  2507  	c.Assert(len(targetsMeta.Signatures), Equals, 1)
  2508  	role1Meta := &data.Signed{}
  2509  	c.Assert(json.Unmarshal(m["role1.json"], role1Meta), IsNil)
  2510  	c.Assert(len(role1Meta.Signatures), Equals, 0)
  2511  
  2512  	c.Assert(r.Snapshot(), DeepEquals, ErrInsufficientSignatures{"role1.json", verify.ErrNoSignatures})
  2513  
  2514  	// Sign role1.json.
  2515  	c.Assert(local.SaveSigner("role1", role1Key), IsNil)
  2516  	c.Assert(r.Sign("role1.json"), IsNil)
  2517  
  2518  	m, err = local.GetMeta()
  2519  	c.Assert(err, IsNil)
  2520  	targetsMeta = &data.Signed{}
  2521  	c.Assert(json.Unmarshal(m["targets.json"], targetsMeta), IsNil)
  2522  	c.Assert(len(targetsMeta.Signatures), Equals, 1)
  2523  	role1Meta = &data.Signed{}
  2524  	c.Assert(json.Unmarshal(m["role1.json"], role1Meta), IsNil)
  2525  	c.Assert(len(role1Meta.Signatures), Equals, 1)
  2526  
  2527  	c.Assert(r.Snapshot(), IsNil)
  2528  	c.Assert(r.Timestamp(), IsNil)
  2529  	c.Assert(r.Commit(), IsNil)
  2530  }
  2531  
  2532  func (rs *RepoSuite) TestAddOrUpdateSignatureWithDelegations(c *C) {
  2533  	tmp := newTmpDir(c)
  2534  	local := FileSystemStore(tmp.path, nil)
  2535  	r, err := NewRepo(local)
  2536  	c.Assert(err, IsNil)
  2537  
  2538  	// Add one key to each role
  2539  	genKey(c, r, "root")
  2540  	genKey(c, r, "targets")
  2541  	genKey(c, r, "snapshot")
  2542  	genKey(c, r, "timestamp")
  2543  
  2544  	role1Key, err := keys.GenerateEd25519Key()
  2545  	c.Assert(err, IsNil)
  2546  
  2547  	role1 := data.DelegatedRole{
  2548  		Name:      "role1",
  2549  		KeyIDs:    role1Key.PublicData().IDs(),
  2550  		Paths:     []string{"A/*", "B/*"},
  2551  		Threshold: 1,
  2552  	}
  2553  	err = r.AddDelegatedRole("targets", role1, []*data.PublicKey{
  2554  		role1Key.PublicData(),
  2555  	})
  2556  	c.Assert(err, IsNil)
  2557  
  2558  	// targets.json should be signed, but role1.json is not signed because there
  2559  	// is no key in the local store.
  2560  	m, err := local.GetMeta()
  2561  	c.Assert(err, IsNil)
  2562  	targetsMeta := &data.Signed{}
  2563  	c.Assert(json.Unmarshal(m["targets.json"], targetsMeta), IsNil)
  2564  	c.Assert(len(targetsMeta.Signatures), Equals, 1)
  2565  	role1Meta := &data.Signed{}
  2566  	c.Assert(json.Unmarshal(m["role1.json"], role1Meta), IsNil)
  2567  	c.Assert(len(role1Meta.Signatures), Equals, 0)
  2568  
  2569  	c.Assert(r.Snapshot(), DeepEquals, ErrInsufficientSignatures{"role1.json", verify.ErrNoSignatures})
  2570  
  2571  	// Sign role1.json.
  2572  	canonical, err := cjson.EncodeCanonical(role1Meta.Signed)
  2573  	c.Assert(err, IsNil)
  2574  	sig, err := role1Key.SignMessage(canonical)
  2575  	c.Assert(err, IsNil)
  2576  	err = r.AddOrUpdateSignature("role1.json", data.Signature{
  2577  		KeyID:     role1Key.PublicData().IDs()[0],
  2578  		Signature: sig,
  2579  	})
  2580  	c.Assert(err, IsNil)
  2581  
  2582  	m, err = local.GetMeta()
  2583  	c.Assert(err, IsNil)
  2584  	targetsMeta = &data.Signed{}
  2585  	c.Assert(json.Unmarshal(m["targets.json"], targetsMeta), IsNil)
  2586  	c.Assert(len(targetsMeta.Signatures), Equals, 1)
  2587  	role1Meta = &data.Signed{}
  2588  	c.Assert(json.Unmarshal(m["role1.json"], role1Meta), IsNil)
  2589  	c.Assert(len(role1Meta.Signatures), Equals, 1)
  2590  
  2591  	c.Assert(r.Snapshot(), IsNil)
  2592  	c.Assert(r.Timestamp(), IsNil)
  2593  	c.Assert(r.Commit(), IsNil)
  2594  }
  2595  
  2596  // Test the offline signature flow: Payload -> SignPayload -> AddSignature
  2597  func (rs *RepoSuite) TestOfflineFlow(c *C) {
  2598  	// Set up repo.
  2599  	meta := make(map[string]json.RawMessage)
  2600  	local := MemoryStore(meta, nil)
  2601  	r, err := NewRepo(local)
  2602  	c.Assert(err, IsNil)
  2603  	c.Assert(r.Init(false), IsNil)
  2604  	// Use ECDSA because it has a newline which is a difference between JSON and cJSON.
  2605  	_, err = r.GenKeyWithSchemeAndExpires("root", data.DefaultExpires("root"), data.KeySchemeECDSA_SHA2_P256)
  2606  	c.Assert(err, IsNil)
  2607  
  2608  	// Get the payload to sign
  2609  	_, err = r.Payload("badrole.json")
  2610  	c.Assert(err, Equals, ErrMissingMetadata{"badrole.json"})
  2611  	_, err = r.Payload("root")
  2612  	c.Assert(err, Equals, ErrMissingMetadata{"root"})
  2613  	payload, err := r.Payload("root.json")
  2614  	c.Assert(err, IsNil)
  2615  
  2616  	root, err := r.SignedMeta("root.json")
  2617  	c.Assert(err, IsNil)
  2618  	rootCanonical, err := cjson.EncodeCanonical(root.Signed)
  2619  	c.Assert(err, IsNil)
  2620  	if !bytes.Equal(payload, rootCanonical) {
  2621  		c.Fatalf("Payload(): not canonical.\n%s\n%s", string(payload), string(rootCanonical))
  2622  	}
  2623  
  2624  	// Sign the payload
  2625  	_, err = r.SignRaw("targets", payload)
  2626  	c.Assert(err, Equals, ErrNoKeys{"targets"})
  2627  	signatures, err := r.SignRaw("root", payload)
  2628  	c.Assert(err, IsNil)
  2629  	c.Assert(len(signatures), Equals, 1)
  2630  
  2631  	// Add the payload signatures back
  2632  	for _, sig := range signatures {
  2633  		// This method checks that the signature verifies!
  2634  		err = r.AddOrUpdateSignature("root.json", sig)
  2635  		c.Assert(err, IsNil)
  2636  	}
  2637  }
  2638  
  2639  // Regression test: Snapshotting an invalid root should fail.
  2640  func (rs *RepoSuite) TestSnapshotWithInvalidRoot(c *C) {
  2641  	files := map[string][]byte{"foo.txt": []byte("foo")}
  2642  	local := MemoryStore(make(map[string]json.RawMessage), files)
  2643  	r, err := NewRepo(local)
  2644  	c.Assert(err, IsNil)
  2645  
  2646  	// Init should create targets.json, but not signed yet
  2647  	r.Init(false)
  2648  
  2649  	genKey(c, r, "root")
  2650  	genKey(c, r, "targets")
  2651  	genKey(c, r, "snapshot")
  2652  	genKey(c, r, "timestamp")
  2653  	c.Assert(r.AddTarget("foo.txt", nil), IsNil)
  2654  
  2655  	// Clear the root signature so that signature verification fails.
  2656  	s, err := r.SignedMeta("root.json")
  2657  	c.Assert(err, IsNil)
  2658  	c.Assert(s.Signatures, HasLen, 1)
  2659  	s.Signatures[0].Signature = data.HexBytes{}
  2660  	b, err := r.jsonMarshal(s)
  2661  	c.Assert(err, IsNil)
  2662  	r.meta["root.json"] = b
  2663  	local.SetMeta("root.json", b)
  2664  
  2665  	// Snapshotting should fail.
  2666  	c.Assert(r.Snapshot(), Equals, ErrInsufficientSignatures{
  2667  		"root.json", verify.ErrRoleThreshold{Expected: 1, Actual: 0}})
  2668  
  2669  	// Correctly sign root
  2670  	c.Assert(r.Sign("root.json"), IsNil)
  2671  	c.Assert(r.Snapshot(), IsNil)
  2672  	c.Assert(r.Timestamp(), IsNil)
  2673  	c.Assert(r.Commit(), IsNil)
  2674  }
  2675  
  2676  // Regression test: Do not omit length in target metadata files.
  2677  func (rs *RepoSuite) TestTargetMetadataLength(c *C) {
  2678  	files := map[string][]byte{"foo.txt": []byte("")}
  2679  	local := MemoryStore(make(map[string]json.RawMessage), files)
  2680  	r, err := NewRepo(local)
  2681  	c.Assert(err, IsNil)
  2682  
  2683  	// Init should create targets.json, but not signed yet
  2684  	r.Init(false)
  2685  
  2686  	genKey(c, r, "root")
  2687  	genKey(c, r, "targets")
  2688  	genKey(c, r, "snapshot")
  2689  	genKey(c, r, "timestamp")
  2690  	c.Assert(r.AddTarget("foo.txt", nil), IsNil)
  2691  	c.Assert(r.Snapshot(), IsNil)
  2692  	c.Assert(r.Timestamp(), IsNil)
  2693  	c.Assert(r.Commit(), IsNil)
  2694  
  2695  	// Check length field of foo.txt exists.
  2696  	meta, err := local.GetMeta()
  2697  	c.Assert(err, IsNil)
  2698  	targetsJSON, ok := meta["targets.json"]
  2699  	if !ok {
  2700  		c.Fatal("missing targets metadata")
  2701  	}
  2702  	s := &data.Signed{}
  2703  	c.Assert(json.Unmarshal(targetsJSON, s), IsNil)
  2704  	fmt.Fprint(os.Stderr, s.Signed)
  2705  	var objMap map[string]json.RawMessage
  2706  	c.Assert(json.Unmarshal(s.Signed, &objMap), IsNil)
  2707  	targetsMap, ok := objMap["targets"]
  2708  	if !ok {
  2709  		c.Fatal("missing targets field in targets metadata")
  2710  	}
  2711  	c.Assert(json.Unmarshal(targetsMap, &objMap), IsNil)
  2712  	targetsMap, ok = objMap["foo.txt"]
  2713  	if !ok {
  2714  		c.Fatal("missing foo.txt in targets")
  2715  	}
  2716  	c.Assert(json.Unmarshal(targetsMap, &objMap), IsNil)
  2717  	lengthMsg, ok := objMap["length"]
  2718  	if !ok {
  2719  		c.Fatal("missing length field in foo.txt file meta")
  2720  	}
  2721  	var length int64
  2722  	c.Assert(json.Unmarshal(lengthMsg, &length), IsNil)
  2723  	c.Assert(length, Equals, int64(0))
  2724  }
  2725  
  2726  func (rs *RepoSuite) TestDeprecatedHexEncodedKeysFails(c *C) {
  2727  	files := map[string][]byte{"foo.txt": []byte("foo")}
  2728  	local := MemoryStore(make(map[string]json.RawMessage), files)
  2729  	r, err := NewRepo(local)
  2730  	c.Assert(err, IsNil)
  2731  
  2732  	r.Init(false)
  2733  	// Add a root key with hex-encoded ecdsa format
  2734  	signer, err := keys.GenerateEcdsaKey()
  2735  	c.Assert(err, IsNil)
  2736  	type deprecatedP256Verifier struct {
  2737  		PublicKey data.HexBytes `json:"public"`
  2738  	}
  2739  	pub := signer.PublicKey
  2740  	keyValBytes, err := json.Marshal(&deprecatedP256Verifier{PublicKey: elliptic.Marshal(pub.Curve, pub.X, pub.Y)})
  2741  	c.Assert(err, IsNil)
  2742  	publicData := &data.PublicKey{
  2743  		Type:       data.KeyTypeECDSA_SHA2_P256,
  2744  		Scheme:     data.KeySchemeECDSA_SHA2_P256,
  2745  		Algorithms: data.HashAlgorithms,
  2746  		Value:      keyValBytes,
  2747  	}
  2748  	err = r.AddVerificationKey("root", publicData)
  2749  	c.Assert(err, IsNil)
  2750  	// TODO: AddVerificationKey does no validation, so perform a sign operation.
  2751  	c.Assert(r.Sign("root.json"), ErrorMatches, "tuf: error unmarshalling key: invalid PEM value")
  2752  }
  2753  

View as plain text