Skip to content

Commit f8ae525

Browse files
author
Volodymyr Paprotski
committed
[FAB-3194] Fixes from whitebox testing with PKCS11
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 <[email protected]>
1 parent 56b6d12 commit f8ae525

15 files changed

+441
-283
lines changed

bccsp/factory/factory.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ var (
4141
// Factories' Initialization Error
4242
factoriesInitError error
4343

44-
logger = logging.MustGetLogger("BCCSP_FACTORY")
44+
logger = logging.MustGetLogger("bccsp")
4545
)
4646

4747
// BCCSPFactory is used to get instances of the BCCSP interface.

bccsp/factory/factory_test.go

+3-33
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@ import (
2323
"os"
2424
"testing"
2525

26+
"github.com/hyperledger/fabric/bccsp/pkcs11"
2627
"github.com/spf13/viper"
2728
)
2829

2930
func TestMain(m *testing.M) {
3031
flag.Parse()
31-
lib, pin, label, enable := findPKCS11Lib()
32+
lib, pin, label := pkcs11.FindPKCS11Lib()
3233

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

58-
if !enable {
59+
if lib == "" {
5960
fmt.Printf("Could not find PKCS11 libraries, running without\n")
6061
yamlCFG = `
6162
BCCSP:
@@ -121,34 +122,3 @@ func TestGetBCCSP(t *testing.T) {
121122
t.Fatal("Failed Software BCCSP. Nil instance.")
122123
}
123124
}
124-
125-
func findPKCS11Lib() (lib, pin, label string, enablePKCS11tests bool) {
126-
//FIXME: Till we workout the configuration piece, look for the libraries in the familiar places
127-
lib = os.Getenv("PKCS11_LIB")
128-
if lib == "" {
129-
pin = "98765432"
130-
label = "ForFabric"
131-
possibilities := []string{
132-
"/usr/lib/softhsm/libsofthsm2.so", //Debian
133-
"/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so", //Ubuntu
134-
"/usr/lib/s390x-linux-gnu/softhsm/libsofthsm2.so", //Ubuntu
135-
"/usr/lib/powerpc64le-linux-gnu/softhsm/libsofthsm2.so", //Power
136-
"/usr/local/Cellar/softhsm/2.1.0/lib/softhsm/libsofthsm2.so", //MacOS
137-
}
138-
for _, path := range possibilities {
139-
if _, err := os.Stat(path); !os.IsNotExist(err) {
140-
lib = path
141-
enablePKCS11tests = true
142-
break
143-
}
144-
}
145-
if lib == "" {
146-
enablePKCS11tests = false
147-
}
148-
} else {
149-
enablePKCS11tests = true
150-
pin = os.Getenv("PKCS11_PIN")
151-
label = os.Getenv("PKCS11_LABEL")
152-
}
153-
return lib, pin, label, enablePKCS11tests
154-
}

bccsp/factory/nopkcs11.go

+15
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,18 @@ func InitFactories(config *FactoryOpts) error {
6868

6969
return factoriesInitError
7070
}
71+
72+
// GetBCCSPFromOpts returns a BCCSP created according to the options passed in input.
73+
func GetBCCSPFromOpts(config *FactoryOpts) (bccsp.BCCSP, error) {
74+
var f BCCSPFactory
75+
switch config.ProviderName {
76+
case "SW":
77+
f = &SWFactory{}
78+
}
79+
80+
csp, err := f.Get(config)
81+
if err != nil {
82+
return nil, fmt.Errorf("Could not initialize BCCSP %s [%s]", f.Name(), err)
83+
}
84+
return csp, nil
85+
}

bccsp/factory/pkcs11.go

+21-3
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ import (
2121
"fmt"
2222

2323
"github.com/hyperledger/fabric/bccsp"
24+
"github.com/hyperledger/fabric/bccsp/pkcs11"
2425
)
2526

2627
type FactoryOpts struct {
27-
ProviderName string `mapstructure:"default" json:"default" yaml:"Default"`
28-
SwOpts *SwOpts `mapstructure:"SW,omitempty" json:"SW,omitempty" yaml:"SwOpts"`
29-
Pkcs11Opts *PKCS11Opts `mapstructure:"PKCS11,omitempty" json:"PKCS11,omitempty" yaml:"PKCS11"`
28+
ProviderName string `mapstructure:"default" json:"default" yaml:"Default"`
29+
SwOpts *SwOpts `mapstructure:"SW,omitempty" json:"SW,omitempty" yaml:"SwOpts"`
30+
Pkcs11Opts *pkcs11.PKCS11Opts `mapstructure:"PKCS11,omitempty" json:"PKCS11,omitempty" yaml:"PKCS11"`
3031
}
3132

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

7980
return factoriesInitError
8081
}
82+
83+
// GetBCCSPFromOpts returns a BCCSP created according to the options passed in input.
84+
func GetBCCSPFromOpts(config *FactoryOpts) (bccsp.BCCSP, error) {
85+
var f BCCSPFactory
86+
switch config.ProviderName {
87+
case "SW":
88+
f = &SWFactory{}
89+
case "PKCS11":
90+
f = &PKCS11Factory{}
91+
}
92+
93+
csp, err := f.Get(config)
94+
if err != nil {
95+
return nil, fmt.Errorf("Could not initialize BCCSP %s [%s]", f.Name(), err)
96+
}
97+
return csp, nil
98+
}

bccsp/factory/pkcs11factory.go

+2-26
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func (f *PKCS11Factory) Name() string {
4242
// Get returns an instance of BCCSP using Opts.
4343
func (f *PKCS11Factory) Get(config *FactoryOpts) (bccsp.BCCSP, error) {
4444
// Validate arguments
45-
if config == nil || config.SwOpts == nil {
45+
if config == nil || config.Pkcs11Opts == nil {
4646
return nil, errors.New("Invalid config. It must not be nil.")
4747
}
4848

@@ -62,29 +62,5 @@ func (f *PKCS11Factory) Get(config *FactoryOpts) (bccsp.BCCSP, error) {
6262
// Default to DummyKeystore
6363
ks = sw.NewDummyKeyStore()
6464
}
65-
err := pkcs11.InitPKCS11(p11Opts.Library, p11Opts.Pin, p11Opts.Label)
66-
if err != nil {
67-
return nil, fmt.Errorf("Failed initializing PKCS11 library %s %s [%s]",
68-
p11Opts.Library, p11Opts.Label, err)
69-
}
70-
return pkcs11.New(p11Opts.SecLevel, p11Opts.HashFamily, ks)
71-
}
72-
73-
// PKCS11Opts contains options for the P11Factory
74-
type PKCS11Opts struct {
75-
// Default algorithms when not specified (Deprecated?)
76-
SecLevel int `mapstructure:"security" json:"security"`
77-
HashFamily string `mapstructure:"hash" json:"hash"`
78-
79-
// Keystore options
80-
Ephemeral bool `mapstructure:"tempkeys,omitempty" json:"tempkeys,omitempty"`
81-
FileKeystore *FileKeystoreOpts `mapstructure:"filekeystore,omitempty" json:"filekeystore,omitempty"`
82-
DummyKeystore *DummyKeystoreOpts `mapstructure:"dummykeystore,omitempty" json:"dummykeystore,omitempty"`
83-
84-
// PKCS11 options
85-
Library string `mapstructure:"library" json:"library"`
86-
Label string `mapstructure:"label" json:"label"`
87-
Pin string `mapstructure:"pin" json:"pin"`
88-
Sensitive bool `mapstructure:"sensitivekeys,omitempty" json:"sensitivekeys,omitempty"`
89-
SoftVerify bool `mapstructure:"softwareverify,omitempty" json:"softwareverify,omitempty"`
65+
return pkcs11.New(*p11Opts, ks)
9066
}

bccsp/pkcs11/conf.go

+27
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,30 @@ func (conf *config) setSecurityLevelSHA3(level int) (err error) {
8383
}
8484
return
8585
}
86+
87+
// PKCS11Opts contains options for the P11Factory
88+
type PKCS11Opts struct {
89+
// Default algorithms when not specified (Deprecated?)
90+
SecLevel int `mapstructure:"security" json:"security"`
91+
HashFamily string `mapstructure:"hash" json:"hash"`
92+
93+
// Keystore options
94+
Ephemeral bool `mapstructure:"tempkeys,omitempty" json:"tempkeys,omitempty"`
95+
FileKeystore *FileKeystoreOpts `mapstructure:"filekeystore,omitempty" json:"filekeystore,omitempty"`
96+
DummyKeystore *DummyKeystoreOpts `mapstructure:"dummykeystore,omitempty" json:"dummykeystore,omitempty"`
97+
98+
// PKCS11 options
99+
Library string `mapstructure:"library" json:"library"`
100+
Label string `mapstructure:"label" json:"label"`
101+
Pin string `mapstructure:"pin" json:"pin"`
102+
Sensitive bool `mapstructure:"sensitivekeys,omitempty" json:"sensitivekeys,omitempty"`
103+
SoftVerify bool `mapstructure:"softwareverify,omitempty" json:"softwareverify,omitempty"`
104+
}
105+
106+
// Since currently only ECDSA operations go to PKCS11, need a keystore still
107+
// Pluggable Keystores, could add JKS, P12, etc..
108+
type FileKeystoreOpts struct {
109+
KeyStorePath string `mapstructure:"keystore" json:"keystore" yaml:"KeyStore"`
110+
}
111+
112+
type DummyKeystoreOpts struct{}

bccsp/pkcs11/ecdsa.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ limitations under the License.
1616
package pkcs11
1717

1818
import (
19+
"crypto/ecdsa"
1920
"crypto/elliptic"
2021
"encoding/asn1"
2122
"errors"
@@ -73,7 +74,7 @@ func unmarshalECDSASignature(raw []byte) (*big.Int, *big.Int, error) {
7374
}
7475

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

114-
return verifyECDSA(k.ski, digest, r, s, k.pub.Curve.Params().BitSize/8)
115+
if csp.softVerify {
116+
return ecdsa.Verify(k.pub, digest, r, s), nil
117+
} else {
118+
return csp.verifyP11ECDSA(k.ski, digest, r, s, k.pub.Curve.Params().BitSize/8)
119+
}
115120
}

0 commit comments

Comments
 (0)