func (rb *repoBuilder) loadTargets(content []byte, minVersion int, allowExpired bool) error { roleName := data.CanonicalTargetsRole targetsRole, err := rb.repo.Root.BuildBaseRole(roleName) if err != nil { // this should never happen, since it's already been validated return err } signedObj, err := rb.bytesToSignedAndValidateSigs(targetsRole, content) if err != nil { return err } signedTargets, err := data.TargetsFromSigned(signedObj, roleName) if err != nil { return err } if err := signed.VerifyVersion(&(signedTargets.Signed.SignedCommon), minVersion); err != nil { return err } if !allowExpired { // check must go at the end because all other validation should pass if err := signed.VerifyExpiry(&(signedTargets.Signed.SignedCommon), roleName); err != nil { return err } } signedTargets.Signatures = signedObj.Signatures rb.repo.Targets[roleName] = signedTargets return nil }
func (rb *repoBuilder) loadTimestamp(content []byte, minVersion int, allowExpired bool) error { roleName := data.CanonicalTimestampRole timestampRole, err := rb.repo.Root.BuildBaseRole(roleName) if err != nil { // this should never happen, since it's already been validated return err } signedObj, err := rb.bytesToSignedAndValidateSigs(timestampRole, content) if err != nil { return err } signedTimestamp, err := data.TimestampFromSigned(signedObj) if err != nil { return err } if err := signed.VerifyVersion(&(signedTimestamp.Signed.SignedCommon), minVersion); err != nil { return err } if !allowExpired { // check must go at the end because all other validation should pass if err := signed.VerifyExpiry(&(signedTimestamp.Signed.SignedCommon), roleName); err != nil { return err } } if err := rb.validateChecksumsFromTimestamp(signedTimestamp); err != nil { return err } rb.repo.Timestamp = signedTimestamp return nil }
// loadRoot loads a root if one has not been loaded func (rb *repoBuilder) loadRoot(content []byte, minVersion int, allowExpired bool) error { roleName := data.CanonicalRootRole signedObj, err := rb.bytesToSigned(content, data.CanonicalRootRole) if err != nil { return err } // ValidateRoot validates against the previous root's role, as well as validates that the root // itself is self-consistent with its own signatures and thresholds. // This assumes that ValidateRoot calls data.RootFromSigned, which validates // the metadata, rather than just unmarshalling signedObject into a SignedRoot object itself. signedRoot, err := trustpinning.ValidateRoot(rb.prevRoot, signedObj, rb.gun, rb.trustpin) if err != nil { return err } if err := signed.VerifyVersion(&(signedRoot.Signed.SignedCommon), minVersion); err != nil { return err } if !allowExpired { // check must go at the end because all other validation should pass if err := signed.VerifyExpiry(&(signedRoot.Signed.SignedCommon), roleName); err != nil { return err } } rootRole, err := signedRoot.BuildBaseRole(data.CanonicalRootRole) if err != nil { // this should never happen since the root has been validated return err } rb.repo.Root = signedRoot rb.repo.originalRootRole = rootRole return nil }
func (rb *repoBuilder) loadDelegation(roleName string, content []byte, minVersion int, allowExpired bool) error { delegationRole, err := rb.repo.GetDelegationRole(roleName) if err != nil { return err } signedObj, err := rb.bytesToSignedAndValidateSigs(delegationRole.BaseRole, content) if err != nil { return err } signedTargets, err := data.TargetsFromSigned(signedObj, roleName) if err != nil { return err } if err := signed.VerifyVersion(&(signedTargets.Signed.SignedCommon), minVersion); err != nil { return err } if !allowExpired { // check must go at the end because all other validation should pass if err := signed.VerifyExpiry(&(signedTargets.Signed.SignedCommon), roleName); err != nil { return err } } rb.repo.Targets[roleName] = signedTargets return nil }
// This changes the root key func TestSwizzlerChangeRootKey(t *testing.T) { f, origMeta := createNewSwizzler(t) err := f.ChangeRootKey() require.NoError(t, err) // we want to test these in a specific order roles := []string{data.CanonicalRootRole, data.CanonicalTargetsRole, data.CanonicalSnapshotRole, data.CanonicalTimestampRole, "targets/a", "targets/a/b"} for _, role := range roles { origMeta := origMeta[role] newMeta, err := f.MetadataCache.GetMeta(role, store.NoSizeLimit) require.NoError(t, err) // the threshold for base roles is set in root switch role { case data.CanonicalRootRole: require.False(t, bytes.Equal(origMeta, newMeta)) origRoot, newRoot := &data.SignedRoot{}, &data.SignedRoot{} require.NoError(t, json.Unmarshal(origMeta, origRoot)) require.NoError(t, json.Unmarshal(newMeta, newRoot)) require.NotEqual(t, len(origRoot.Signed.Keys), len(newRoot.Signed.Keys)) for r, origRole := range origRoot.Signed.Roles { newRole := newRoot.Signed.Roles[r] require.Len(t, origRole.KeyIDs, 1) require.Len(t, newRole.KeyIDs, 1) if r == data.CanonicalRootRole { require.NotEqual(t, origRole.KeyIDs[0], newRole.KeyIDs[0]) } else { require.Equal(t, origRole.KeyIDs[0], newRole.KeyIDs[0]) } } rootRole, err := newRoot.BuildBaseRole(data.CanonicalRootRole) require.NoError(t, err) signedThing, err := newRoot.ToSigned() require.NoError(t, err) require.NoError(t, signed.VerifySignatures(signedThing, rootRole)) require.NoError(t, signed.VerifyVersion(&(newRoot.Signed.SignedCommon), 1)) default: require.True(t, bytes.Equal(origMeta, newMeta), "bytes have changed for role %s", role) } } }
func (rb *repoBuilder) loadSnapshot(content []byte, minVersion int, allowExpired bool) error { roleName := data.CanonicalSnapshotRole snapshotRole, err := rb.repo.Root.BuildBaseRole(roleName) if err != nil { // this should never happen, since it's already been validated return err } signedObj, err := rb.bytesToSignedAndValidateSigs(snapshotRole, content) if err != nil { return err } signedSnapshot, err := data.SnapshotFromSigned(signedObj) if err != nil { return err } if err := signed.VerifyVersion(&(signedSnapshot.Signed.SignedCommon), minVersion); err != nil { return err } if !allowExpired { // check must go at the end because all other validation should pass if err := signed.VerifyExpiry(&(signedSnapshot.Signed.SignedCommon), roleName); err != nil { return err } } // at this point, the only thing left to validate is existing checksums - we can use // this snapshot to bootstrap the next builder if needed - and we don't need to do // the 2-value assignment since we've already validated the signedSnapshot, which MUST // have root metadata rootMeta := signedSnapshot.Signed.Meta[data.CanonicalRootRole] rb.nextRootChecksum = &rootMeta if err := rb.validateChecksumsFromSnapshot(signedSnapshot); err != nil { return err } rb.repo.Snapshot = signedSnapshot return nil }
func (rb *repoBuilder) loadDelegation(roleName string, content []byte, minVersion int, allowExpired bool) error { delegationRole, err := rb.repo.GetDelegationRole(roleName) if err != nil { return err } // bytesToSigned checks checksum signedObj, err := rb.bytesToSigned(content, roleName) if err != nil { return err } signedTargets, err := data.TargetsFromSigned(signedObj, roleName) if err != nil { return err } if err := signed.VerifyVersion(&(signedTargets.Signed.SignedCommon), minVersion); err != nil { // don't capture in invalidRoles because the role we received is a rollback return err } // verify signature if err := signed.VerifySignatures(signedObj, delegationRole.BaseRole); err != nil { rb.invalidRoles.Targets[roleName] = signedTargets return err } if !allowExpired { // check must go at the end because all other validation should pass if err := signed.VerifyExpiry(&(signedTargets.Signed.SignedCommon), roleName); err != nil { rb.invalidRoles.Targets[roleName] = signedTargets return err } } signedTargets.Signatures = signedObj.Signatures rb.repo.Targets[roleName] = signedTargets return nil }