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] }