Skip to content

Commit

Permalink
[FAB-3441] Add more input validation tests to BCCSP.
Browse files Browse the repository at this point in the history
This changeset adds a set of unit-tests to SW part
of the default BCCSP. It focuses on passing a few
invalid inputs and verifying the correct/expected behavior.

Change-Id: I232c5bf77dd264cb93d88394f03dee92f19d40e2
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
  • Loading branch information
adecaro authored and yacovm committed Apr 30, 2017
1 parent f367a52 commit 084b02f
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 15 deletions.
58 changes: 48 additions & 10 deletions bccsp/mocks/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,27 @@ type MockBCCSP struct {
}

func (*MockBCCSP) KeyGen(opts bccsp.KeyGenOpts) (k bccsp.Key, err error) {
panic("implement me")
panic("Not yet implemented")
}

func (*MockBCCSP) KeyDeriv(k bccsp.Key, opts bccsp.KeyDerivOpts) (dk bccsp.Key, err error) {
panic("implement me")
panic("Not yet implemented")
}

func (*MockBCCSP) KeyImport(raw interface{}, opts bccsp.KeyImportOpts) (k bccsp.Key, err error) {
panic("implement me")
panic("Not yet implemented")
}

func (*MockBCCSP) GetKey(ski []byte) (k bccsp.Key, err error) {
panic("implement me")
panic("Not yet implemented")
}

func (*MockBCCSP) Hash(msg []byte, opts bccsp.HashOpts) (hash []byte, err error) {
panic("implement me")
panic("Not yet implemented")
}

func (*MockBCCSP) GetHash(opts bccsp.HashOpts) (h hash.Hash, err error) {
panic("implement me")
panic("Not yet implemented")
}

func (b *MockBCCSP) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) (signature []byte, err error) {
Expand All @@ -80,11 +80,11 @@ func (b *MockBCCSP) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.Sig
}

func (*MockBCCSP) Encrypt(k bccsp.Key, plaintext []byte, opts bccsp.EncrypterOpts) (ciphertext []byte, err error) {
panic("implement me")
panic("Not yet implemented")
}

func (*MockBCCSP) Decrypt(k bccsp.Key, ciphertext []byte, opts bccsp.DecrypterOpts) (plaintext []byte, err error) {
panic("implement me")
panic("Not yet implemented")
}

type MockKey struct {
Expand All @@ -100,15 +100,15 @@ func (m *MockKey) Bytes() ([]byte, error) {
}

func (*MockKey) SKI() []byte {
panic("implement me")
panic("Not yet implemented")
}

func (m *MockKey) Symmetric() bool {
return m.Symm
}

func (*MockKey) Private() bool {
panic("implement me")
panic("Not yet implemented")
}

func (m *MockKey) PublicKey() (bccsp.Key, error) {
Expand All @@ -122,3 +122,41 @@ type SignerOpts struct {
func (o *SignerOpts) HashFunc() crypto.Hash {
return o.HashFuncValue
}

type KeyGenOpts struct{}

func (*KeyGenOpts) Algorithm() string {
return "Mock KeyGenOpts"
}

func (*KeyGenOpts) Ephemeral() bool {
panic("Not yet implemented")
}

type KeyStore struct {
GetKeyValue bccsp.Key
GetKeyErr error
StoreKeyErr error
}

func (*KeyStore) ReadOnly() bool {
panic("Not yet implemented")
}

func (ks *KeyStore) GetKey(ski []byte) (k bccsp.Key, err error) {
return ks.GetKeyValue, ks.GetKeyErr
}

func (ks *KeyStore) StoreKey(k bccsp.Key) (err error) {
return ks.StoreKeyErr
}

type KeyImportOpts struct{}

func (*KeyImportOpts) Algorithm() string {
return "Mock KeyImportOpts"
}

func (*KeyImportOpts) Ephemeral() bool {
panic("Not yet implemented")
}
10 changes: 5 additions & 5 deletions bccsp/sw/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ func (csp *impl) KeyImport(raw interface{}, opts bccsp.KeyImportOpts) (k bccsp.K
}

default:
return nil, errors.New("Import Key Options not recognized")
return nil, fmt.Errorf("Unsupported 'KeyImportOptions' provided [%v]", opts)
}
}

Expand Down Expand Up @@ -665,7 +665,7 @@ func (csp *impl) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) (signat

return k.(*rsaPrivateKey).privKey.Sign(rand.Reader, digest, opts)
default:
return nil, fmt.Errorf("Key type not recognized [%s]", k)
return nil, fmt.Errorf("Unsupported 'SignKey' provided [%v]", k)
}
}

Expand Down Expand Up @@ -717,7 +717,7 @@ func (csp *impl) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.Signer
return false, fmt.Errorf("Opts type not recognized [%s]", opts)
}
default:
return false, fmt.Errorf("Key type not recognized [%s]", k)
return false, fmt.Errorf("Unsupported 'VerifyKey' provided [%v]", k)
}
}

Expand All @@ -741,7 +741,7 @@ func (csp *impl) Encrypt(k bccsp.Key, plaintext []byte, opts bccsp.EncrypterOpts
return nil, fmt.Errorf("Mode not recognized [%s]", opts)
}
default:
return nil, fmt.Errorf("Key type not recognized [%s]", k)
return nil, fmt.Errorf("Unsupported 'EncryptKey' provided [%v]", k)
}
}

Expand All @@ -765,6 +765,6 @@ func (csp *impl) Decrypt(k bccsp.Key, ciphertext []byte, opts bccsp.DecrypterOpt
return nil, fmt.Errorf("Mode not recognized [%s]", opts)
}
default:
return nil, fmt.Errorf("Key type not recognized [%s]", k)
return nil, fmt.Errorf("Unsupported 'DecryptKey' provided [%v]", k)
}
}
158 changes: 158 additions & 0 deletions bccsp/sw/sw_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/*
Copyright IBM Corp. 2017 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package sw

import (
"errors"
"strings"
"testing"

"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/bccsp/mocks"
"github.com/stretchr/testify/assert"
)

func TestKeyGenInvalidInputs(t *testing.T) {
// Init a BCCSP instance with a key store that returns an error on store
csp, err := New(256, "SHA2", &mocks.KeyStore{StoreKeyErr: errors.New("cannot store key")})
assert.NoError(t, err)

_, err = csp.KeyGen(nil)
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Invalid Opts parameter. It must not be nil."))

_, err = csp.KeyGen(&mocks.KeyGenOpts{})
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Unrecognized KeyGenOpts provided ["))

_, err = csp.KeyGen(&bccsp.ECDSAP256KeyGenOpts{})
assert.Error(t, err, "Generation of a non-ephemeral key must fail. KeyStore is programmed to fail.")
assert.True(t, strings.Contains(err.Error(), "cannot store key"), "Failure must be due to the KeyStore")
}

func TestKeyDerivInvalidInputs(t *testing.T) {
csp, err := New(256, "SHA2", &mocks.KeyStore{})
assert.NoError(t, err)

_, err = csp.KeyDeriv(nil, &bccsp.ECDSAReRandKeyOpts{})
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Invalid Key. It must not be nil."))

_, err = csp.KeyDeriv(&mocks.MockKey{}, &bccsp.ECDSAReRandKeyOpts{})
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Key type not recognized ["))
}

func TestKeyImportInvalidInputs(t *testing.T) {
csp, err := New(256, "SHA2", &mocks.KeyStore{})
assert.NoError(t, err)

_, err = csp.KeyImport(nil, &bccsp.AES256ImportKeyOpts{})
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Invalid raw. Cannot be nil"))

_, err = csp.KeyImport([]byte{0, 1, 2, 3, 4}, nil)
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Invalid Opts parameter. It must not be nil."))

_, err = csp.KeyImport([]byte{0, 1, 2, 3, 4}, &mocks.KeyImportOpts{})
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Unsupported 'KeyImportOptions' provided ["))
}

func TestGetKeyInvalidInputs(t *testing.T) {
// Init a BCCSP instance with a key store that returns an error on get
csp, err := New(256, "SHA2", &mocks.KeyStore{GetKeyErr: errors.New("cannot get key")})
assert.NoError(t, err)

_, err = csp.GetKey(nil)
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "cannot get key"))

// Init a BCCSP instance with a key store that returns a given key
k := &mocks.MockKey{}
csp, err = New(256, "SHA2", &mocks.KeyStore{GetKeyValue: k})
assert.NoError(t, err)
// No SKI is needed here
k2, err := csp.GetKey(nil)
assert.NoError(t, err)
assert.Equal(t, k, k2, "Keys must be the same.")
}

func TestSignInvalidInputs(t *testing.T) {
csp, err := New(256, "SHA2", &mocks.KeyStore{})
assert.NoError(t, err)

_, err = csp.Sign(nil, []byte{1, 2, 3, 5}, nil)
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Invalid Key. It must not be nil."))

_, err = csp.Sign(&mocks.MockKey{}, nil, nil)
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Invalid digest. Cannot be empty."))

_, err = csp.Sign(&mocks.MockKey{}, []byte{1, 2, 3, 5}, nil)
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Unsupported 'SignKey' provided ["))
}

func TestVerifyInvalidInputs(t *testing.T) {
csp, err := New(256, "SHA2", &mocks.KeyStore{})
assert.NoError(t, err)

_, err = csp.Verify(nil, []byte{1, 2, 3, 5}, []byte{1, 2, 3, 5}, nil)
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Invalid Key. It must not be nil."))

_, err = csp.Verify(&mocks.MockKey{}, nil, []byte{1, 2, 3, 5}, nil)
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Invalid signature. Cannot be empty."))

_, err = csp.Verify(&mocks.MockKey{}, []byte{1, 2, 3, 5}, nil, nil)
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Invalid digest. Cannot be empty."))

_, err = csp.Verify(&mocks.MockKey{}, []byte{1, 2, 3, 5}, []byte{1, 2, 3, 5}, nil)
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Unsupported 'VerifyKey' provided ["))
}

func TestEncryptInvalidInputs(t *testing.T) {
csp, err := New(256, "SHA2", &mocks.KeyStore{})
assert.NoError(t, err)

_, err = csp.Encrypt(nil, []byte{1, 2, 3, 4}, &bccsp.AESCBCPKCS7ModeOpts{})
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Invalid Key. It must not be nil."))

_, err = csp.Encrypt(&mocks.MockKey{}, []byte{1, 2, 3, 4}, &bccsp.AESCBCPKCS7ModeOpts{})
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Unsupported 'EncryptKey' provided ["))
}

func TestDecryptInvalidInputs(t *testing.T) {
csp, err := New(256, "SHA2", &mocks.KeyStore{})
assert.NoError(t, err)

_, err = csp.Decrypt(nil, []byte{1, 2, 3, 4}, &bccsp.AESCBCPKCS7ModeOpts{})
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Invalid Key. It must not be nil."))

_, err = csp.Decrypt(&mocks.MockKey{}, []byte{1, 2, 3, 4}, &bccsp.AESCBCPKCS7ModeOpts{})
assert.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "Unsupported 'DecryptKey' provided ["))
}

0 comments on commit 084b02f

Please sign in to comment.