blob: 04f5bf1c441b977b9bf4c6334efaa0906e31ad3a [file] [log] [blame]
package verify
import (
"github.com/theupdateframework/go-tuf/data"
"github.com/theupdateframework/go-tuf/internal/roles"
"github.com/theupdateframework/go-tuf/pkg/keys"
)
type Role struct {
KeyIDs map[string]struct{}
Threshold int
}
func (r *Role) ValidKey(id string) bool {
_, ok := r.KeyIDs[id]
return ok
}
type DB struct {
roles map[string]*Role
verifiers map[string]keys.Verifier
}
func NewDB() *DB {
return &DB{
roles: make(map[string]*Role),
verifiers: make(map[string]keys.Verifier),
}
}
// NewDBFromDelegations returns a DB that verifies delegations
// of a given Targets.
func NewDBFromDelegations(d *data.Delegations) (*DB, error) {
db := &DB{
roles: make(map[string]*Role, len(d.Roles)),
verifiers: make(map[string]keys.Verifier, len(d.Keys)),
}
for _, r := range d.Roles {
if _, ok := roles.TopLevelRoles[r.Name]; ok {
return nil, ErrInvalidDelegatedRole
}
role := &data.Role{Threshold: r.Threshold, KeyIDs: r.KeyIDs}
if err := db.AddRole(r.Name, role); err != nil {
return nil, err
}
}
for id, k := range d.Keys {
if err := db.AddKey(id, k); err != nil {
return nil, err
}
}
return db, nil
}
func (db *DB) AddKey(id string, k *data.PublicKey) error {
verifier, err := keys.GetVerifier(k)
if err != nil {
return err // ErrInvalidKey
}
// TUF is considering in TAP-12 removing the
// requirement that the keyid hash algorithm be derived
// from the public key. So to be forwards compatible,
// we allow any key ID, rather than checking k.ContainsID(id)
//
// AddKey should be idempotent, so we allow re-adding the same PublicKey.
//
// TAP-12: https://github.com/theupdateframework/taps/blob/master/tap12.md
if oldVerifier, exists := db.verifiers[id]; exists && oldVerifier.Public() != verifier.Public() {
return ErrRepeatID{id}
}
db.verifiers[id] = verifier
return nil
}
func (db *DB) AddRole(name string, r *data.Role) error {
if r.Threshold < 1 {
return ErrInvalidThreshold
}
role := &Role{
KeyIDs: make(map[string]struct{}),
Threshold: r.Threshold,
}
for _, id := range r.KeyIDs {
role.KeyIDs[id] = struct{}{}
}
db.roles[name] = role
return nil
}
func (db *DB) GetVerifier(id string) (keys.Verifier, error) {
k, ok := db.verifiers[id]
if !ok {
return nil, ErrMissingKey
}
return k, nil
}
func (db *DB) GetRole(name string) *Role {
return db.roles[name]
}