Skip to content

Commit

Permalink
[FAB-3194] Fixes from whitebox testing with PKCS11
Browse files Browse the repository at this point in the history
Several fixes from testing E2E with HSM.

Tested with SoftHSM as well as IBM CEX5S.

- Biggest change: make most pkcs11 operations class-based
   (This is so that multiple CSPs can be instantiated at once.
    This in turn is useful for cryptogen, to generate in multiple
    pkcs11 tokens at once)
- viper.UnmarshalKey ignores ENV vars. Luckily Jason already has
  viperutil that does not
- some further pkcs11 option cleanup,
- implement softverify flag
- implement sensitive flag, since real card prohibits key import

Change-Id: Ic40323f1a32499da0f61ab0658371a1af95c564d
Signed-off-by: Volodymyr Paprotski <vpaprots@ca.ibm.com>
  • Loading branch information
Volodymyr Paprotski committed Apr 19, 2017
1 parent 56b6d12 commit f8ae525
Show file tree
Hide file tree
Showing 15 changed files with 441 additions and 283 deletions.
2 changes: 1 addition & 1 deletion bccsp/factory/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ var (
// Factories' Initialization Error
factoriesInitError error

logger = logging.MustGetLogger("BCCSP_FACTORY")
logger = logging.MustGetLogger("bccsp")
)

// BCCSPFactory is used to get instances of the BCCSP interface.
Expand Down
36 changes: 3 additions & 33 deletions bccsp/factory/factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ import (
"os"
"testing"

"github.com/hyperledger/fabric/bccsp/pkcs11"
"github.com/spf13/viper"
)

func TestMain(m *testing.M) {
flag.Parse()
lib, pin, label, enable := findPKCS11Lib()
lib, pin, label := pkcs11.FindPKCS11Lib()

var jsonBCCSP, yamlBCCSP *FactoryOpts
jsonCFG := []byte(
Expand All @@ -55,7 +56,7 @@ BCCSP:
Label: %s
`, lib, pin, label)

if !enable {
if lib == "" {
fmt.Printf("Could not find PKCS11 libraries, running without\n")
yamlCFG = `
BCCSP:
Expand Down Expand Up @@ -121,34 +122,3 @@ func TestGetBCCSP(t *testing.T) {
t.Fatal("Failed Software BCCSP. Nil instance.")
}
}

func findPKCS11Lib() (lib, pin, label string, enablePKCS11tests bool) {
//FIXME: Till we workout the configuration piece, look for the libraries in the familiar places
lib = os.Getenv("PKCS11_LIB")
if lib == "" {
pin = "98765432"
label = "ForFabric"
possibilities := []string{
"/usr/lib/softhsm/libsofthsm2.so", //Debian
"/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so", //Ubuntu
"/usr/lib/s390x-linux-gnu/softhsm/libsofthsm2.so", //Ubuntu
"/usr/lib/powerpc64le-linux-gnu/softhsm/libsofthsm2.so", //Power
"/usr/local/Cellar/softhsm/2.1.0/lib/softhsm/libsofthsm2.so", //MacOS
}
for _, path := range possibilities {
if _, err := os.Stat(path); !os.IsNotExist(err) {
lib = path
enablePKCS11tests = true
break
}
}
if lib == "" {
enablePKCS11tests = false
}
} else {
enablePKCS11tests = true
pin = os.Getenv("PKCS11_PIN")
label = os.Getenv("PKCS11_LABEL")
}
return lib, pin, label, enablePKCS11tests
}
15 changes: 15 additions & 0 deletions bccsp/factory/nopkcs11.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,18 @@ func InitFactories(config *FactoryOpts) error {

return factoriesInitError
}

// GetBCCSPFromOpts returns a BCCSP created according to the options passed in input.
func GetBCCSPFromOpts(config *FactoryOpts) (bccsp.BCCSP, error) {
var f BCCSPFactory
switch config.ProviderName {
case "SW":
f = &SWFactory{}
}

csp, err := f.Get(config)
if err != nil {
return nil, fmt.Errorf("Could not initialize BCCSP %s [%s]", f.Name(), err)
}
return csp, nil
}
24 changes: 21 additions & 3 deletions bccsp/factory/pkcs11.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ import (
"fmt"

"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/bccsp/pkcs11"
)

type FactoryOpts struct {
ProviderName string `mapstructure:"default" json:"default" yaml:"Default"`
SwOpts *SwOpts `mapstructure:"SW,omitempty" json:"SW,omitempty" yaml:"SwOpts"`
Pkcs11Opts *PKCS11Opts `mapstructure:"PKCS11,omitempty" json:"PKCS11,omitempty" yaml:"PKCS11"`
ProviderName string `mapstructure:"default" json:"default" yaml:"Default"`
SwOpts *SwOpts `mapstructure:"SW,omitempty" json:"SW,omitempty" yaml:"SwOpts"`
Pkcs11Opts *pkcs11.PKCS11Opts `mapstructure:"PKCS11,omitempty" json:"PKCS11,omitempty" yaml:"PKCS11"`
}

// InitFactories must be called before using factory interfaces
Expand Down Expand Up @@ -78,3 +79,20 @@ func InitFactories(config *FactoryOpts) error {

return factoriesInitError
}

// GetBCCSPFromOpts returns a BCCSP created according to the options passed in input.
func GetBCCSPFromOpts(config *FactoryOpts) (bccsp.BCCSP, error) {
var f BCCSPFactory
switch config.ProviderName {
case "SW":
f = &SWFactory{}
case "PKCS11":
f = &PKCS11Factory{}
}

csp, err := f.Get(config)
if err != nil {
return nil, fmt.Errorf("Could not initialize BCCSP %s [%s]", f.Name(), err)
}
return csp, nil
}
28 changes: 2 additions & 26 deletions bccsp/factory/pkcs11factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (f *PKCS11Factory) Name() string {
// Get returns an instance of BCCSP using Opts.
func (f *PKCS11Factory) Get(config *FactoryOpts) (bccsp.BCCSP, error) {
// Validate arguments
if config == nil || config.SwOpts == nil {
if config == nil || config.Pkcs11Opts == nil {
return nil, errors.New("Invalid config. It must not be nil.")
}

Expand All @@ -62,29 +62,5 @@ func (f *PKCS11Factory) Get(config *FactoryOpts) (bccsp.BCCSP, error) {
// Default to DummyKeystore
ks = sw.NewDummyKeyStore()
}
err := pkcs11.InitPKCS11(p11Opts.Library, p11Opts.Pin, p11Opts.Label)
if err != nil {
return nil, fmt.Errorf("Failed initializing PKCS11 library %s %s [%s]",
p11Opts.Library, p11Opts.Label, err)
}
return pkcs11.New(p11Opts.SecLevel, p11Opts.HashFamily, ks)
}

// PKCS11Opts contains options for the P11Factory
type PKCS11Opts struct {
// Default algorithms when not specified (Deprecated?)
SecLevel int `mapstructure:"security" json:"security"`
HashFamily string `mapstructure:"hash" json:"hash"`

// Keystore options
Ephemeral bool `mapstructure:"tempkeys,omitempty" json:"tempkeys,omitempty"`
FileKeystore *FileKeystoreOpts `mapstructure:"filekeystore,omitempty" json:"filekeystore,omitempty"`
DummyKeystore *DummyKeystoreOpts `mapstructure:"dummykeystore,omitempty" json:"dummykeystore,omitempty"`

// PKCS11 options
Library string `mapstructure:"library" json:"library"`
Label string `mapstructure:"label" json:"label"`
Pin string `mapstructure:"pin" json:"pin"`
Sensitive bool `mapstructure:"sensitivekeys,omitempty" json:"sensitivekeys,omitempty"`
SoftVerify bool `mapstructure:"softwareverify,omitempty" json:"softwareverify,omitempty"`
return pkcs11.New(*p11Opts, ks)
}
27 changes: 27 additions & 0 deletions bccsp/pkcs11/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,30 @@ func (conf *config) setSecurityLevelSHA3(level int) (err error) {
}
return
}

// PKCS11Opts contains options for the P11Factory
type PKCS11Opts struct {
// Default algorithms when not specified (Deprecated?)
SecLevel int `mapstructure:"security" json:"security"`
HashFamily string `mapstructure:"hash" json:"hash"`

// Keystore options
Ephemeral bool `mapstructure:"tempkeys,omitempty" json:"tempkeys,omitempty"`
FileKeystore *FileKeystoreOpts `mapstructure:"filekeystore,omitempty" json:"filekeystore,omitempty"`
DummyKeystore *DummyKeystoreOpts `mapstructure:"dummykeystore,omitempty" json:"dummykeystore,omitempty"`

// PKCS11 options
Library string `mapstructure:"library" json:"library"`
Label string `mapstructure:"label" json:"label"`
Pin string `mapstructure:"pin" json:"pin"`
Sensitive bool `mapstructure:"sensitivekeys,omitempty" json:"sensitivekeys,omitempty"`
SoftVerify bool `mapstructure:"softwareverify,omitempty" json:"softwareverify,omitempty"`
}

// Since currently only ECDSA operations go to PKCS11, need a keystore still
// Pluggable Keystores, could add JKS, P12, etc..
type FileKeystoreOpts struct {
KeyStorePath string `mapstructure:"keystore" json:"keystore" yaml:"KeyStore"`
}

type DummyKeystoreOpts struct{}
9 changes: 7 additions & 2 deletions bccsp/pkcs11/ecdsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ limitations under the License.
package pkcs11

import (
"crypto/ecdsa"
"crypto/elliptic"
"encoding/asn1"
"errors"
Expand Down Expand Up @@ -73,7 +74,7 @@ func unmarshalECDSASignature(raw []byte) (*big.Int, *big.Int, error) {
}

func (csp *impl) signECDSA(k ecdsaPrivateKey, digest []byte, opts bccsp.SignerOpts) (signature []byte, err error) {
r, s, err := signECDSA(k.ski, digest)
r, s, err := csp.signP11ECDSA(k.ski, digest)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -111,5 +112,9 @@ func (csp *impl) verifyECDSA(k ecdsaPublicKey, signature, digest []byte, opts bc
return false, fmt.Errorf("Invalid S. Must be smaller than half the order [%s][%s].", s, halfOrder)
}

return verifyECDSA(k.ski, digest, r, s, k.pub.Curve.Params().BitSize/8)
if csp.softVerify {
return ecdsa.Verify(k.pub, digest, r, s), nil
} else {
return csp.verifyP11ECDSA(k.ski, digest, r, s, k.pub.Curve.Params().BitSize/8)
}
}
Loading

0 comments on commit f8ae525

Please sign in to comment.