fix: add mutex to key map to avoid concurrent read/write on first key use under certain conditions

This commit is contained in:
Cassandra Heart 2023-10-26 02:34:51 -05:00
parent 52cfe0abb0
commit cbeec8b1ee
No known key found for this signature in database
GPG Key ID: 6352152859385958

View File

@ -7,6 +7,7 @@ import (
"crypto/rand" "crypto/rand"
"encoding/hex" "encoding/hex"
"os" "os"
"sync"
"github.com/cloudflare/circl/sign/ed448" "github.com/cloudflare/circl/sign/ed448"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -21,6 +22,7 @@ type FileKeyManager struct {
logger *zap.Logger logger *zap.Logger
key ByteString key ByteString
store map[string]Key store map[string]Key
storeMx sync.Mutex
} }
var UnsupportedKeyTypeErr = errors.New("unsupported key type") var UnsupportedKeyTypeErr = errors.New("unsupported key type")
@ -204,9 +206,12 @@ func (f *FileKeyManager) DeleteKey(id string) error {
d := yaml.NewEncoder(file) d := yaml.NewEncoder(file)
f.storeMx.Lock()
delete(f.store, id) delete(f.store, id)
err = d.Encode(f.store) err = d.Encode(f.store)
f.storeMx.Unlock()
return errors.Wrap(err, "could not store") return errors.Wrap(err, "could not store")
} }
@ -224,6 +229,7 @@ func (f *FileKeyManager) GetKey(id string) (key *Key, err error) {
func (f *FileKeyManager) ListKeys() ([]*Key, error) { func (f *FileKeyManager) ListKeys() ([]*Key, error) {
keys := []*Key{} keys := []*Key{}
f.storeMx.Lock()
for k := range f.store { for k := range f.store {
storeKey, err := f.read(k) storeKey, err := f.read(k)
if err != nil { if err != nil {
@ -231,6 +237,7 @@ func (f *FileKeyManager) ListKeys() ([]*Key, error) {
} }
keys = append(keys, &storeKey) keys = append(keys, &storeKey)
} }
f.storeMx.Unlock()
return keys, nil return keys, nil
} }
@ -258,6 +265,7 @@ func (f *FileKeyManager) save(id string, key Key) error {
return errors.Wrap(err, "could not encrypt") return errors.Wrap(err, "could not encrypt")
} }
f.storeMx.Lock()
f.store[id] = Key{ f.store[id] = Key{
Id: key.Id, Id: key.Id,
Type: key.Type, Type: key.Type,
@ -266,6 +274,8 @@ func (f *FileKeyManager) save(id string, key Key) error {
} }
err = d.Encode(f.store) err = d.Encode(f.store)
f.storeMx.Unlock()
return errors.Wrap(err, "could not store") return errors.Wrap(err, "could not store")
} }
@ -284,25 +294,31 @@ func (f *FileKeyManager) read(id string) (Key, error) {
defer file.Close() defer file.Close()
d := yaml.NewDecoder(file) d := yaml.NewDecoder(file)
f.storeMx.Lock()
if err = d.Decode(f.store); err != nil { if err = d.Decode(f.store); err != nil {
f.storeMx.Unlock()
return Key{}, errors.Wrap(err, "could not decode") return Key{}, errors.Wrap(err, "could not decode")
} }
if _, ok := f.store[id]; !ok { if _, ok := f.store[id]; !ok {
f.storeMx.Unlock()
return Key{}, KeyNotFoundErr return Key{}, KeyNotFoundErr
} }
data, err := f.decrypt(f.store[id].PrivateKey) data, err := f.decrypt(f.store[id].PrivateKey)
if err != nil { if err != nil {
f.storeMx.Unlock()
return Key{}, errors.Wrap(err, "could not decrypt") return Key{}, errors.Wrap(err, "could not decrypt")
} }
return Key{ key := Key{
Id: f.store[id].Id, Id: f.store[id].Id,
Type: f.store[id].Type, Type: f.store[id].Type,
PublicKey: f.store[id].PublicKey, PublicKey: f.store[id].PublicKey,
PrivateKey: data, PrivateKey: data,
}, nil }
f.storeMx.Unlock()
return key, nil
} }
func (f *FileKeyManager) encrypt(data []byte) ([]byte, error) { func (f *FileKeyManager) encrypt(data []byte) ([]byte, error) {