Add revocation to certificate stores

This commit is contained in:
Torjus Håkestad 2021-12-06 17:28:48 +01:00
parent 67014f7af7
commit f20da8ed23
4 changed files with 81 additions and 13 deletions

View File

@ -21,6 +21,7 @@ var bktKey = []byte("files")
var bktKeyCerts = []byte("certs") var bktKeyCerts = []byte("certs")
var bktKeyKeys = []byte("keys") var bktKeyKeys = []byte("keys")
var bktKeyUsers = []byte("users") var bktKeyUsers = []byte("users")
var bktKeyRevoked = []byte("revoked")
func NewBoltStore(path string) (*BoltStore, error) { func NewBoltStore(path string) (*BoltStore, error) {
s := &BoltStore{} s := &BoltStore{}
@ -42,6 +43,9 @@ func NewBoltStore(path string) (*BoltStore, error) {
if _, err := t.CreateBucketIfNotExists(bktKeyUsers); err != nil { if _, err := t.CreateBucketIfNotExists(bktKeyUsers); err != nil {
return err return err
} }
if _, err := t.CreateBucketIfNotExists(bktKeyRevoked); err != nil {
return err
}
return nil return nil
}) })
if err != nil { if err != nil {
@ -202,6 +206,29 @@ func (s *BoltStore) ListCertificates() ([]string, error) {
return ids, nil return ids, nil
} }
func (s *BoltStore) Revoke(serial string) error {
return s.db.Update(func(tx *bolt.Tx) error {
bkt := tx.Bucket(bktKeyRevoked)
return bkt.Put([]byte(serial), []byte{'r'})
})
}
func (s *BoltStore) IsRevoked(serial string) (bool, error) {
var revoked bool
err := s.db.View(func(tx *bolt.Tx) error {
bkt := tx.Bucket(bktKeyRevoked)
status := bkt.Get([]byte(serial))
if status != nil {
revoked = true
}
return nil
})
if err != nil {
return false, err
}
return revoked, nil
}
var _ UserStore = &BoltStore{} var _ UserStore = &BoltStore{}
func (s *BoltStore) StoreUser(user *pb.User) error { func (s *BoltStore) StoreUser(user *pb.User) error {

View File

@ -10,22 +10,25 @@ import (
) )
type MemoryStore struct { type MemoryStore struct {
filesLock sync.RWMutex filesLock sync.RWMutex
files map[string]*pb.File files map[string]*pb.File
certLock sync.RWMutex certLock sync.RWMutex
certs map[string][]byte certs map[string][]byte
keyLock sync.RWMutex keyLock sync.RWMutex
keys map[string][]byte keys map[string][]byte
usersLock sync.RWMutex usersLock sync.RWMutex
users map[string]*pb.User users map[string]*pb.User
revokedCerts map[string]struct{}
revokedLock sync.RWMutex
} }
func NewMemoryStore() *MemoryStore { func NewMemoryStore() *MemoryStore {
return &MemoryStore{ return &MemoryStore{
files: make(map[string]*pb.File), files: make(map[string]*pb.File),
certs: make(map[string][]byte), certs: make(map[string][]byte),
keys: make(map[string][]byte), keys: make(map[string][]byte),
users: make(map[string]*pb.User), users: make(map[string]*pb.User),
revokedCerts: make(map[string]struct{}),
} }
} }
@ -147,6 +150,22 @@ func (s *MemoryStore) ListCertificates() ([]string, error) {
return certIDs, nil return certIDs, nil
} }
func (s *MemoryStore) Revoke(serial string) error {
s.revokedLock.Lock()
defer s.revokedLock.Unlock()
s.revokedCerts[serial] = struct{}{}
return nil
}
func (s *MemoryStore) IsRevoked(serial string) (bool, error) {
s.revokedLock.RLock()
defer s.revokedLock.RUnlock()
_, revoked := s.revokedCerts[serial]
return revoked, nil
}
/////////////// ///////////////
// UserStore // // UserStore //
/////////////// ///////////////

View File

@ -23,6 +23,8 @@ type CertificateStore interface {
GetKey(id string) (*ecdsa.PrivateKey, error) GetKey(id string) (*ecdsa.PrivateKey, error)
StoreKey(id string, key *ecdsa.PrivateKey) error StoreKey(id string, key *ecdsa.PrivateKey) error
ListCertificates() ([]string, error) ListCertificates() ([]string, error)
Revoke(serial string) error
IsRevoked(serial string) (bool, error)
} }
type UserStore interface { type UserStore interface {

View File

@ -79,7 +79,7 @@ func doCertificateStoreTest(s store.CertificateStore, t *testing.T) {
// Create cert and key // Create cert and key
unsigned := &x509.Certificate{ unsigned := &x509.Certificate{
SerialNumber: big.NewInt(time.Now().Unix()), SerialNumber: big.NewInt(time.Now().UnixMilli()),
Subject: pkix.Name{ Subject: pkix.Name{
Organization: []string{"ezshare"}, Organization: []string{"ezshare"},
Country: []string{"No"}, Country: []string{"No"},
@ -142,6 +142,26 @@ func doCertificateStoreTest(s store.CertificateStore, t *testing.T) {
if !retrievedKey.Equal(privateKey) { if !retrievedKey.Equal(privateKey) {
t.Errorf("Retrieved key does not match stored.") t.Errorf("Retrieved key does not match stored.")
} }
// Revoke
isRevoked, err := s.IsRevoked(cert.SerialNumber.String())
if err != nil {
t.Fatalf("Error checking if certificate is revoked: %s", err)
}
if isRevoked {
t.Fatalf("Unrevoked certificate is revoked")
}
if err := s.Revoke(cert.SerialNumber.String()); err != nil {
t.Fatalf("Error revoking certificate: %s", err)
}
isRevoked, err = s.IsRevoked(cert.SerialNumber.String())
if err != nil {
t.Fatalf("Error checking if certificate is revoked: %s", err)
}
if !isRevoked {
t.Fatalf("Revoked certificate is not revoked")
}
}) })
} }