Skip to content

Commit

Permalink
BCCSP KeyStore cleanup
Browse files Browse the repository at this point in the history
This change-set introduces New* methods to instantiate
file-based key stores and dummy key stores.
The purpose is to streamline the instantiation of keystore
and allow reusability in the pkcs11 package.

Change-Id: I1cf6b3e6a9c3244bdc46f6aa164a49acb1e4b1f0
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
  • Loading branch information
adecaro committed Feb 20, 2017
1 parent e829d2e commit f4e359f
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 41 deletions.
7 changes: 3 additions & 4 deletions bccsp/factory/pkcs11factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,16 @@ func (f *PKCS11Factory) Get(config *FactoryOpts) (bccsp.BCCSP, error) {
//TODO: PKCS11 does not need a keystore, but we have not migrated all of PKCS11 BCCSP to PKCS11 yet
var ks bccsp.KeyStore
if p11Opts.Ephemeral == true {
ks = &sw.DummyKeyStore{}
ks = sw.NewDummyKeyStore()
} else if p11Opts.FileKeystore != nil {
fks := &sw.FileBasedKeyStore{}
err := fks.Init(nil, p11Opts.FileKeystore.KeyStorePath, false)
fks, err := sw.NewFileBasedKeyStore(nil, p11Opts.FileKeystore.KeyStorePath, false)
if err != nil {
return nil, fmt.Errorf("Failed to initialize software key store: %s", err)
}
ks = fks
} else {
// Default to DummyKeystore
ks = &sw.DummyKeyStore{}
ks = sw.NewDummyKeyStore()
}
err := pkcs11.InitPKCS11(p11Opts.Library, p11Opts.Pin, p11Opts.Label)
if err != nil {
Expand Down
7 changes: 3 additions & 4 deletions bccsp/factory/swfactory.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,16 @@ func (f *SWFactory) Get(config *FactoryOpts) (bccsp.BCCSP, error) {

var ks bccsp.KeyStore
if swOpts.Ephemeral == true {
ks = &sw.DummyKeyStore{}
ks = sw.NewDummyKeyStore()
} else if swOpts.FileKeystore != nil {
fks := &sw.FileBasedKeyStore{}
err := fks.Init(nil, swOpts.FileKeystore.KeyStorePath, false)
fks, err := sw.NewFileBasedKeyStore(nil, swOpts.FileKeystore.KeyStorePath, false)
if err != nil {
return nil, fmt.Errorf("Failed to initialize software key store: %s", err)
}
ks = fks
} else {
// Default to DummyKeystore
ks = &sw.DummyKeyStore{}
ks = sw.NewDummyKeyStore()
}

return sw.New(swOpts.SecLevel, swOpts.HashFamily, ks)
Expand Down
2 changes: 1 addition & 1 deletion bccsp/pkcs11/dummyks.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"github.com/hyperledger/fabric/bccsp"
)

// DummyKeyStore is a read-only KeyStore that neither loads nor stores keys.
// dummyKeyStore is a read-only KeyStore that neither loads nor stores keys.
type DummyKeyStore struct {
}

Expand Down
2 changes: 1 addition & 1 deletion bccsp/pkcs11/fileks.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
"github.com/hyperledger/fabric/bccsp/utils"
)

// FileBasedKeyStore is a folder-based KeyStore.
// fileBasedKeyStore is a folder-based KeyStore.
// Each key is stored in a separated file whose name contains the key's SKI
// and flags to identity the key's type. All the keys are stored in
// a folder whose path is provided at initialization time.
Expand Down
2 changes: 1 addition & 1 deletion bccsp/pkcs11/impl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func TestMain(m *testing.M) {
os.Exit(-1)
}

currentSWBCCSP, err = sw.New(config.securityLevel, config.hashFamily, &sw.DummyKeyStore{})
currentSWBCCSP, err = sw.New(config.securityLevel, config.hashFamily, sw.NewDummyKeyStore())
if err != nil {
fmt.Printf("Failed initiliazing BCCSP at [%d, %s]: [%s]", config.securityLevel, config.hashFamily, err)
os.Exit(-1)
Expand Down
16 changes: 11 additions & 5 deletions bccsp/sw/dummyks.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,29 @@ import (
"github.com/hyperledger/fabric/bccsp"
)

// DummyKeyStore is a read-only KeyStore that neither loads nor stores keys.
type DummyKeyStore struct {
// NewDummyKeyStore instantiate a dummy key store
// that neither loads nor stores keys
func NewDummyKeyStore() bccsp.KeyStore {
return &dummyKeyStore{}
}

// dummyKeyStore is a read-only KeyStore that neither loads nor stores keys.
type dummyKeyStore struct {
}

// ReadOnly returns true if this KeyStore is read only, false otherwise.
// If ReadOnly is true then StoreKey will fail.
func (ks *DummyKeyStore) ReadOnly() bool {
func (ks *dummyKeyStore) ReadOnly() bool {
return true
}

// GetKey returns a key object whose SKI is the one passed.
func (ks *DummyKeyStore) GetKey(ski []byte) (k bccsp.Key, err error) {
func (ks *dummyKeyStore) GetKey(ski []byte) (k bccsp.Key, err error) {
return nil, errors.New("Key not found. This is a dummy KeyStore")
}

// StoreKey stores the key k in this KeyStore.
// If this KeyStore is read only then the method will fail.
func (ks *DummyKeyStore) StoreKey(k bccsp.Key) (err error) {
func (ks *dummyKeyStore) StoreKey(k bccsp.Key) (err error) {
return errors.New("Cannot store key. This is a dummy read-only KeyStore")
}
47 changes: 28 additions & 19 deletions bccsp/sw/fileks.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,23 @@ import (
"github.com/hyperledger/fabric/bccsp/utils"
)

// FileBasedKeyStore is a folder-based KeyStore.
// NewFileBasedKeyStore instantiated a file-based key store at a given position.
// The key store can be encrypted if a non-empty password is specifiec.
// It can be also be set as read only. In this case, any store operation
// will be forbidden
func NewFileBasedKeyStore(pwd []byte, path string, readOnly bool) (bccsp.KeyStore, error) {
ks := &fileBasedKeyStore{}
return ks, ks.Init(pwd, path, readOnly)
}

// fileBasedKeyStore is a folder-based KeyStore.
// Each key is stored in a separated file whose name contains the key's SKI
// and flags to identity the key's type. All the keys are stored in
// a folder whose path is provided at initialization time.
// The KeyStore can be initialized with a password, this password
// is used to encrypt and decrypt the files storing the keys.
// A KeyStore can be read only to avoid the overwriting of keys.
type FileBasedKeyStore struct {
type fileBasedKeyStore struct {
path string

readOnly bool
Expand All @@ -62,7 +71,7 @@ type FileBasedKeyStore struct {
// key-store is initialized without a password, then retrieving keys from the
// KeyStore will fail.
// A KeyStore can be read only to avoid the overwriting of keys.
func (ks *FileBasedKeyStore) Init(pwd []byte, path string, readOnly bool) error {
func (ks *fileBasedKeyStore) Init(pwd []byte, path string, readOnly bool) error {
// Validate inputs
// pwd can be nil

Expand Down Expand Up @@ -97,12 +106,12 @@ func (ks *FileBasedKeyStore) Init(pwd []byte, path string, readOnly bool) error

// ReadOnly returns true if this KeyStore is read only, false otherwise.
// If ReadOnly is true then StoreKey will fail.
func (ks *FileBasedKeyStore) ReadOnly() bool {
func (ks *fileBasedKeyStore) ReadOnly() bool {
return ks.readOnly
}

// GetKey returns a key object whose SKI is the one passed.
func (ks *FileBasedKeyStore) GetKey(ski []byte) (k bccsp.Key, err error) {
func (ks *fileBasedKeyStore) GetKey(ski []byte) (k bccsp.Key, err error) {
// Validate arguments
if len(ski) == 0 {
return nil, errors.New("Invalid SKI. Cannot be of zero length.")
Expand Down Expand Up @@ -156,7 +165,7 @@ func (ks *FileBasedKeyStore) GetKey(ski []byte) (k bccsp.Key, err error) {

// StoreKey stores the key k in this KeyStore.
// If this KeyStore is read only then the method will fail.
func (ks *FileBasedKeyStore) StoreKey(k bccsp.Key) (err error) {
func (ks *fileBasedKeyStore) StoreKey(k bccsp.Key) (err error) {
if ks.readOnly {
return errors.New("Read only KeyStore.")
}
Expand Down Expand Up @@ -212,7 +221,7 @@ func (ks *FileBasedKeyStore) StoreKey(k bccsp.Key) (err error) {
return
}

func (ks *FileBasedKeyStore) getSuffix(alias string) string {
func (ks *fileBasedKeyStore) getSuffix(alias string) string {
files, _ := ioutil.ReadDir(ks.path)
for _, f := range files {
if strings.HasPrefix(f.Name(), alias) {
Expand All @@ -231,7 +240,7 @@ func (ks *FileBasedKeyStore) getSuffix(alias string) string {
return ""
}

func (ks *FileBasedKeyStore) storePrivateKey(alias string, privateKey interface{}) error {
func (ks *fileBasedKeyStore) storePrivateKey(alias string, privateKey interface{}) error {
rawKey, err := utils.PrivateKeyToPEM(privateKey, ks.pwd)
if err != nil {
logger.Errorf("Failed converting private key to PEM [%s]: [%s]", alias, err)
Expand All @@ -247,7 +256,7 @@ func (ks *FileBasedKeyStore) storePrivateKey(alias string, privateKey interface{
return nil
}

func (ks *FileBasedKeyStore) storePublicKey(alias string, publicKey interface{}) error {
func (ks *fileBasedKeyStore) storePublicKey(alias string, publicKey interface{}) error {
rawKey, err := utils.PublicKeyToPEM(publicKey, ks.pwd)
if err != nil {
logger.Errorf("Failed converting public key to PEM [%s]: [%s]", alias, err)
Expand All @@ -263,7 +272,7 @@ func (ks *FileBasedKeyStore) storePublicKey(alias string, publicKey interface{})
return nil
}

func (ks *FileBasedKeyStore) storeKey(alias string, key []byte) error {
func (ks *fileBasedKeyStore) storeKey(alias string, key []byte) error {
pem, err := utils.AEStoEncryptedPEM(key, ks.pwd)
if err != nil {
logger.Errorf("Failed converting key to PEM [%s]: [%s]", alias, err)
Expand All @@ -279,7 +288,7 @@ func (ks *FileBasedKeyStore) storeKey(alias string, key []byte) error {
return nil
}

func (ks *FileBasedKeyStore) loadPrivateKey(alias string) (interface{}, error) {
func (ks *fileBasedKeyStore) loadPrivateKey(alias string) (interface{}, error) {
path := ks.getPathForAlias(alias, "sk")
logger.Debugf("Loading private key [%s] at [%s]...", alias, path)

Expand All @@ -300,7 +309,7 @@ func (ks *FileBasedKeyStore) loadPrivateKey(alias string) (interface{}, error) {
return privateKey, nil
}

func (ks *FileBasedKeyStore) loadPublicKey(alias string) (interface{}, error) {
func (ks *fileBasedKeyStore) loadPublicKey(alias string) (interface{}, error) {
path := ks.getPathForAlias(alias, "pk")
logger.Debugf("Loading public key [%s] at [%s]...", alias, path)

Expand All @@ -321,7 +330,7 @@ func (ks *FileBasedKeyStore) loadPublicKey(alias string) (interface{}, error) {
return privateKey, nil
}

func (ks *FileBasedKeyStore) loadKey(alias string) ([]byte, error) {
func (ks *fileBasedKeyStore) loadKey(alias string) ([]byte, error) {
path := ks.getPathForAlias(alias, "key")
logger.Debugf("Loading key [%s] at [%s]...", alias, path)

Expand All @@ -342,13 +351,13 @@ func (ks *FileBasedKeyStore) loadKey(alias string) ([]byte, error) {
return key, nil
}

func (ks *FileBasedKeyStore) close() error {
func (ks *fileBasedKeyStore) close() error {
ks.isOpen = false
logger.Debug("Closing keystore...done!")
return nil
}

func (ks *FileBasedKeyStore) createKeyStoreIfNotExists() error {
func (ks *fileBasedKeyStore) createKeyStoreIfNotExists() error {
// Check keystore directory
ksPath := ks.path
missing, err := utils.DirMissingOrEmpty(ksPath)
Expand All @@ -365,7 +374,7 @@ func (ks *FileBasedKeyStore) createKeyStoreIfNotExists() error {
return nil
}

func (ks *FileBasedKeyStore) createKeyStore() error {
func (ks *fileBasedKeyStore) createKeyStore() error {
// Create keystore directory root if it doesn't exist yet
ksPath := ks.path
logger.Debugf("Creating KeyStore at [%s]...", ksPath)
Expand All @@ -376,13 +385,13 @@ func (ks *FileBasedKeyStore) createKeyStore() error {
return nil
}

func (ks *FileBasedKeyStore) deleteKeyStore() error {
func (ks *fileBasedKeyStore) deleteKeyStore() error {
logger.Debugf("Removing KeyStore at [%s].", ks.path)

return os.RemoveAll(ks.path)
}

func (ks *FileBasedKeyStore) openKeyStore() error {
func (ks *fileBasedKeyStore) openKeyStore() error {
if ks.isOpen {
return nil
}
Expand All @@ -392,6 +401,6 @@ func (ks *FileBasedKeyStore) openKeyStore() error {
return nil
}

func (ks *FileBasedKeyStore) getPathForAlias(alias, suffix string) string {
func (ks *fileBasedKeyStore) getPathForAlias(alias, suffix string) string {
return filepath.Join(ks.path, alias+"_"+suffix)
}
6 changes: 3 additions & 3 deletions bccsp/sw/fileks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ import (
)

func TestInvalidStoreKey(t *testing.T) {
ks := &FileBasedKeyStore{}
if err := ks.Init(nil, filepath.Join(os.TempDir(), "bccspks"), false); err != nil {
ks, err := NewFileBasedKeyStore(nil, filepath.Join(os.TempDir(), "bccspks"), false)
if err != nil {
fmt.Printf("Failed initiliazing KeyStore [%s]", err)
os.Exit(-1)
}

err := ks.StoreKey(nil)
err = ks.StoreKey(nil)
if err == nil {
t.Fatal("Error should be different from nil in this case")
}
Expand Down
2 changes: 1 addition & 1 deletion bccsp/sw/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ var (
// NewDefaultSecurityLevel returns a new instance of the software-based BCCSP
// at security level 256, hash family SHA2 and using FolderBasedKeyStore as KeyStore.
func NewDefaultSecurityLevel(keyStorePath string) (bccsp.BCCSP, error) {
ks := &FileBasedKeyStore{}
ks := &fileBasedKeyStore{}
if err := ks.Init(nil, keyStorePath, false); err != nil {
return nil, fmt.Errorf("Failed initializing key store [%s]", err)
}
Expand Down
4 changes: 2 additions & 2 deletions bccsp/sw/impl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ type testConfig struct {
}

func TestMain(m *testing.M) {
ks := &FileBasedKeyStore{}
if err := ks.Init(nil, os.TempDir(), false); err != nil {
ks, err := NewFileBasedKeyStore(nil, os.TempDir(), false);
if err != nil {
fmt.Printf("Failed initiliazing KeyStore [%s]", err)
os.Exit(-1)
}
Expand Down

0 comments on commit f4e359f

Please sign in to comment.