func (c Client) verifyRoot(role string, s *data.Signed, minVersion int) error { // this will confirm that the root has been signed by the old root role // as c.keysDB contains the root keys we bootstrapped with. // Still need to determine if there has been a root key update and // confirm signature with new root key logrus.Debug("verifying root with existing keys") err := signed.Verify(s, role, minVersion, c.keysDB) if err != nil { logrus.Debug("root did not verify with existing keys") return err } // This will cause keyDB to get updated, overwriting any keyIDs associated // with the roles in root.json logrus.Debug("updating known root roles and keys") err = c.local.SetRoot(s) if err != nil { logrus.Error(err.Error()) return err } // verify again now that the old keys have been replaced with the new keys. // TODO(endophage): be more intelligent and only re-verify if we detect // there has been a change in root keys logrus.Debug("verifying root with updated keys") err = signed.Verify(s, role, minVersion, c.keysDB) if err != nil { logrus.Debug("root did not verify with new keys") return err } logrus.Debug("successfully verified root") return nil }
func validateSnapshot(role string, oldSnap *data.SignedSnapshot, snapUpdate storage.MetaUpdate, roles map[string]storage.MetaUpdate, kdb *keys.KeyDB) error { s := &data.Signed{} err := json.Unmarshal(snapUpdate.Data, s) if err != nil { return errors.New("could not parse snapshot") } // version specifically gets validated when writing to store to // better handle race conditions there. if err := signed.Verify(s, role, 0, kdb); err != nil { return err } snap, err := data.SnapshotFromSigned(s) if err != nil { return errors.New("could not parse snapshot") } if !data.ValidTUFType(snap.Signed.Type, data.CanonicalSnapshotRole) { return errors.New("snapshot has wrong type") } err = checkSnapshotEntries(role, oldSnap, snap, roles) if err != nil { return err } return nil }
// downloadTimestamp is responsible for downloading the timestamp.json func (c *Client) downloadTimestamp() error { logrus.Debug("downloadTimestamp") role := data.RoleName("timestamp") // We may not have a cached timestamp if this is the first time // we're interacting with the repo. This will result in the // version being 0 var download bool old := &data.Signed{} version := 0 cachedTS, err := c.cache.GetMeta(role, maxSize) if err == nil { err := json.Unmarshal(cachedTS, old) if err == nil { ts, err := data.TimestampFromSigned(old) if err == nil { version = ts.Signed.Version } } else { old = nil } } // unlike root, targets and snapshot, always try and download timestamps // from remote, only using the cache one if we couldn't reach remote. logrus.Debug("Downloading timestamp") raw, err := c.remote.GetMeta(role, maxSize) var s *data.Signed if err != nil || len(raw) == 0 { if err, ok := err.(store.ErrMetaNotFound); ok { return err } if old == nil { if err == nil { // couldn't retrieve data from server and don't have valid // data in cache. return store.ErrMetaNotFound{} } return err } s = old } else { download = true s = &data.Signed{} err = json.Unmarshal(raw, s) if err != nil { return err } } err = signed.Verify(s, role, version, c.keysDB) if err != nil { return err } logrus.Debug("successfully verified timestamp") if download { c.cache.SetMeta(role, raw) } c.local.SetTimestamp(s) return nil }
// downloadTimestamp is responsible for downloading the timestamp.json func (c *Client) downloadTimestamp() error { role := data.RoleName("timestamp") raw, err := c.remote.GetMeta(role, 5<<20) if err != nil { return err } s := &data.Signed{} err = json.Unmarshal(raw, s) if err != nil { return err } err = signed.Verify(s, role, 0, c.keysDB) if err != nil { return err } c.local.SetTimestamp(s) return nil }
// downloadSnapshot is responsible for downloading the snapshot.json func (c *Client) downloadSnapshot() error { role := data.RoleName("snapshot") size := c.local.Timestamp.Signed.Meta[role].Length raw, err := c.remote.GetMeta(role, size) if err != nil { return err } s := &data.Signed{} err = json.Unmarshal(raw, s) if err != nil { return err } err = signed.Verify(s, role, 0, c.keysDB) if err != nil { return err } c.local.SetSnapshot(s) return nil }
func (c Client) GetTargetsFile(roleName string, keyIDs []string, snapshotMeta data.Files, consistent bool, threshold int) (*data.Signed, error) { rolePath, err := c.RoleTargetsPath(roleName, snapshotMeta, consistent) if err != nil { return nil, err } r, err := c.remote.GetMeta(rolePath, snapshotMeta[roleName].Length) if err != nil { return nil, err } s := &data.Signed{} err = json.Unmarshal(r, s) if err != nil { logrus.Error("Error unmarshalling targets file:", err) return nil, err } err = signed.Verify(s, roleName, 0, c.keysDB) if err != nil { return nil, err } return s, nil }
func validateTargets(role string, roles map[string]storage.MetaUpdate, kdb *keys.KeyDB) (*data.SignedTargets, error) { // TODO: when delegations are being validated, validate parent // role exists for any delegation s := &data.Signed{} err := json.Unmarshal(roles[role].Data, s) if err != nil { return nil, fmt.Errorf("could not parse %s", role) } // version specifically gets validated when writing to store to // better handle race conditions there. if err := signed.Verify(s, role, 0, kdb); err != nil { return nil, err } t, err := data.TargetsFromSigned(s) if err != nil { return nil, err } if !data.ValidTUFType(t.Signed.Type, data.CanonicalTargetsRole) { return nil, fmt.Errorf("%s has wrong type", role) } return t, nil }
func (c Client) getTargetsFile(role string, keyIDs []string, snapshotMeta data.Files, consistent bool, threshold int) (*data.Signed, error) { // require role exists in snapshots roleMeta, ok := snapshotMeta[role] if !ok { return nil, ErrMissingMeta{role: role} } expectedSha256, ok := snapshotMeta[role].Hashes["sha256"] if !ok { return nil, ErrMissingMeta{role: role} } // try to get meta file from content addressed cache var download bool old := &data.Signed{} version := 0 raw, err := c.cache.GetMeta(role, roleMeta.Length) if err != nil || raw == nil { logrus.Debugf("Couldn't not find cached %s, must download", role) download = true } else { // file may have been tampered with on disk. Always check the hash! genHash := sha256.Sum256(raw) if !bytes.Equal(genHash[:], expectedSha256) { download = true } err := json.Unmarshal(raw, old) if err == nil { targ, err := data.TargetsFromSigned(old) if err == nil { version = targ.Signed.Version } else { download = true } } else { download = true } } size := snapshotMeta[role].Length var s *data.Signed if download { rolePath, err := c.RoleTargetsPath(role, hex.EncodeToString(expectedSha256), consistent) if err != nil { return nil, err } raw, s, err = c.downloadSigned(rolePath, size, expectedSha256) if err != nil { return nil, err } } else { logrus.Debug("using cached ", role) s = old } err = signed.Verify(s, role, version, c.keysDB) if err != nil { return nil, err } logrus.Debugf("successfully verified %s", role) if download { // if we error when setting meta, we should continue. err = c.cache.SetMeta(role, raw) if err != nil { logrus.Errorf("Failed to write snapshot to local cache: %s", err.Error()) } } return s, nil }
// downloadSnapshot is responsible for downloading the snapshot.json func (c *Client) downloadSnapshot() error { logrus.Debug("downloadSnapshot") role := data.RoleName("snapshot") if c.local.Timestamp == nil { return ErrMissingMeta{role: "snapshot"} } size := c.local.Timestamp.Signed.Meta[role].Length expectedSha256, ok := c.local.Timestamp.Signed.Meta[role].Hashes["sha256"] if !ok { return ErrMissingMeta{role: "snapshot"} } var download bool old := &data.Signed{} version := 0 raw, err := c.cache.GetMeta(role, size) if raw == nil || err != nil { logrus.Debug("no snapshot in cache, must download") download = true } else { // file may have been tampered with on disk. Always check the hash! genHash := sha256.Sum256(raw) if !bytes.Equal(genHash[:], expectedSha256) { logrus.Debug("hash of snapshot in cache did not match expected hash, must download") download = true } err := json.Unmarshal(raw, old) if err == nil { snap, err := data.TimestampFromSigned(old) if err == nil { version = snap.Signed.Version } else { logrus.Debug("Could not parse Signed part of snapshot, must download") download = true } } else { logrus.Debug("Could not parse snapshot, must download") download = true } } var s *data.Signed if download { raw, s, err = c.downloadSigned(role, size, expectedSha256) if err != nil { return err } } else { logrus.Debug("using cached snapshot") s = old } err = signed.Verify(s, role, version, c.keysDB) if err != nil { return err } logrus.Debug("successfully verified snapshot") snap, err := data.SnapshotFromSigned(s) if err != nil { return err } c.local.SetSnapshot(snap) if download { err = c.cache.SetMeta(role, raw) if err != nil { logrus.Errorf("Failed to write snapshot to local cache: %s", err.Error()) } } return nil }
// downloadSnapshot is responsible for downloading the snapshot.json func (c *Client) downloadSnapshot() error { logrus.Debug("downloadSnapshot") role := data.RoleName("snapshot") size := c.local.Timestamp.Signed.Meta[role].Length expectedSha256, ok := c.local.Timestamp.Signed.Meta[role].Hashes["sha256"] if !ok { return fmt.Errorf("Sha256 is currently the only hash supported by this client. No Sha256 found for snapshot") } var download bool old := &data.Signed{} version := 0 raw, err := c.cache.GetMeta(role, size) if raw == nil || err != nil { logrus.Debug("no snapshot in cache, must download") download = true } else { // file may have been tampered with on disk. Always check the hash! genHash := sha256.Sum256(raw) if !bytes.Equal(genHash[:], expectedSha256) { logrus.Debug("hash of snapshot in cache did not match expected hash, must download") download = true } err := json.Unmarshal(raw, old) if err == nil { snap, err := data.TimestampFromSigned(old) if err == nil { version = snap.Signed.Version } else { logrus.Debug("Could not parse Signed part of snapshot, must download") download = true } } else { logrus.Debug("Could not parse snapshot, must download") download = true } } var s *data.Signed if download { logrus.Debug("downloading new snapshot") raw, err = c.remote.GetMeta(role, size) if err != nil { return err } genHash := sha256.Sum256(raw) if !bytes.Equal(genHash[:], expectedSha256) { return fmt.Errorf("Retrieved snapshot did not verify against hash in timestamp.") } s = &data.Signed{} err = json.Unmarshal(raw, s) if err != nil { return err } } else { logrus.Debug("using cached snapshot") s = old } err = signed.Verify(s, role, version, c.keysDB) if err != nil { return err } logrus.Debug("successfully verified snapshot") c.local.SetSnapshot(s) if download { err = c.cache.SetMeta(role, raw) if err != nil { logrus.Errorf("Failed to write snapshot to local cache: %s", err.Error()) } } return nil }