blob: 7613d5cd4c94c60854ae700096c071f566c02799 [file] [log] [blame]
// Package keys implements an in-memory public key database for TUF.
package keys
import (
"errors"
"github.com/flynn/go-tuf/data"
"github.com/flynn/go-tuf/signed"
)
var (
ErrWrongType = errors.New("tuf: invalid key type")
ErrExists = errors.New("tuf: key already in db")
ErrWrongID = errors.New("tuf: key id mismatch")
ErrInvalidKey = errors.New("tuf: invalid key")
ErrInvalidRole = errors.New("tuf: invalid role")
ErrInvalidKeyID = errors.New("tuf: invalid key id")
ErrInvalidThreshold = errors.New("tuf: invalid role threshold")
)
type Key struct {
ID string
Type string
Public []byte
}
func (k *Key) Serialize() *data.Key {
return &data.Key{
Type: k.Type,
Value: data.KeyValue{Public: k.Public[:]},
}
}
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
keys map[string]*Key
}
func NewDB() *DB {
return &DB{
roles: make(map[string]*Role),
keys: make(map[string]*Key),
}
}
func (db *DB) AddKey(id string, k *data.Key) error {
v, ok := signed.Verifiers[k.Type]
if !ok {
return nil
}
if id != k.ID() {
return ErrWrongID
}
if !v.ValidKey(k.Value.Public) {
return ErrInvalidKey
}
db.keys[id] = &Key{
ID: k.ID(),
Type: k.Type,
Public: k.Value.Public,
}
return nil
}
var validRoles = map[string]struct{}{
"root": {},
"targets": {},
"snapshot": {},
"timestamp": {},
}
func ValidRole(name string) bool {
_, ok := validRoles[name]
return ok
}
func (db *DB) AddRole(name string, r *data.Role) error {
if !ValidRole(name) {
return ErrInvalidRole
}
if r.Threshold < 1 {
return ErrInvalidThreshold
}
role := &Role{
KeyIDs: make(map[string]struct{}),
Threshold: r.Threshold,
}
for _, id := range r.KeyIDs {
if len(id) != data.KeyIDLength {
return ErrInvalidKeyID
}
role.KeyIDs[id] = struct{}{}
}
db.roles[name] = role
return nil
}
func (db *DB) GetKey(id string) *Key {
return db.keys[id]
}
func (db *DB) GetRole(name string) *Role {
return db.roles[name]
}