Skip to content

Commit 5440e98

Browse files
committed
[FAB-3441] bccsp/sw KeyImport test coverage
Using the approach discussed in FAB-3465, this change-sets refactors the way key importation is done at bccsp/sw. Essentially, the switch has been replaced by a map. The approach decouples the testing of the bccsp interface implementation from the cryptographic algorithms. Test-coverage of the entire bccsp/sw is now at more than 90% Change-Id: I662b9b36f1571510f2797cb6396e106c9fd7f7a0 Signed-off-by: Angelo De Caro <[email protected]>
1 parent f533ae6 commit 5440e98

File tree

7 files changed

+431
-181
lines changed

7 files changed

+431
-181
lines changed

bccsp/sw/impl.go

+32-177
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,15 @@ limitations under the License.
1616
package sw
1717

1818
import (
19-
"crypto/ecdsa"
2019
"crypto/elliptic"
21-
"crypto/rsa"
22-
"crypto/x509"
20+
"crypto/sha256"
21+
"crypto/sha512"
2322
"errors"
2423
"fmt"
2524
"hash"
2625
"reflect"
2726

28-
"crypto/sha256"
29-
"crypto/sha512"
30-
3127
"github.com/hyperledger/fabric/bccsp"
32-
"github.com/hyperledger/fabric/bccsp/utils"
3328
"github.com/hyperledger/fabric/common/flogging"
3429
"golang.org/x/crypto/sha3"
3530
)
@@ -130,6 +125,18 @@ func New(securityLevel int, hashFamily string, keyStore bccsp.KeyStore) (bccsp.B
130125
keyDerivers[reflect.TypeOf(&aesPrivateKey{})] = &aesPrivateKeyKeyDeriver{bccsp: impl}
131126
impl.keyDerivers = keyDerivers
132127

128+
// Set the key importers
129+
keyImporters := make(map[reflect.Type]KeyImporter)
130+
keyImporters[reflect.TypeOf(&bccsp.AES256ImportKeyOpts{})] = &aes256ImportKeyOptsKeyImporter{}
131+
keyImporters[reflect.TypeOf(&bccsp.HMACImportKeyOpts{})] = &hmacImportKeyOptsKeyImporter{}
132+
keyImporters[reflect.TypeOf(&bccsp.ECDSAPKIXPublicKeyImportOpts{})] = &ecdsaPKIXPublicKeyImportOptsKeyImporter{}
133+
keyImporters[reflect.TypeOf(&bccsp.ECDSAPrivateKeyImportOpts{})] = &ecdsaPrivateKeyImportOptsKeyImporter{}
134+
keyImporters[reflect.TypeOf(&bccsp.ECDSAGoPublicKeyImportOpts{})] = &ecdsaGoPublicKeyImportOptsKeyImporter{}
135+
keyImporters[reflect.TypeOf(&bccsp.RSAGoPublicKeyImportOpts{})] = &rsaGoPublicKeyImportOptsKeyImporter{}
136+
keyImporters[reflect.TypeOf(&bccsp.X509PublicKeyImportOpts{})] = &x509PublicKeyImportOptsKeyImporter{bccsp: impl}
137+
138+
impl.keyImporters = keyImporters
139+
133140
return impl, nil
134141
}
135142

@@ -140,6 +147,7 @@ type impl struct {
140147

141148
keyGenerators map[reflect.Type]KeyGenerator
142149
keyDerivers map[reflect.Type]KeyDeriver
150+
keyImporters map[reflect.Type]KeyImporter
143151
encryptors map[reflect.Type]Encryptor
144152
decryptors map[reflect.Type]Decryptor
145153
signers map[reflect.Type]Signer
@@ -214,185 +222,32 @@ func (csp *impl) KeyDeriv(k bccsp.Key, opts bccsp.KeyDerivOpts) (dk bccsp.Key, e
214222
func (csp *impl) KeyImport(raw interface{}, opts bccsp.KeyImportOpts) (k bccsp.Key, err error) {
215223
// Validate arguments
216224
if raw == nil {
217-
return nil, errors.New("Invalid raw. Cannot be nil")
225+
return nil, errors.New("Invalid raw. It must not be nil.")
218226
}
219-
220227
if opts == nil {
221-
return nil, errors.New("Invalid Opts parameter. It must not be nil.")
228+
return nil, errors.New("Invalid opts. It must not be nil.")
222229
}
223230

224-
switch opts.(type) {
225-
226-
case *bccsp.AES256ImportKeyOpts:
227-
aesRaw, ok := raw.([]byte)
228-
if !ok {
229-
return nil, errors.New("[AES256ImportKeyOpts] Invalid raw material. Expected byte array.")
230-
}
231-
232-
if len(aesRaw) != 32 {
233-
return nil, fmt.Errorf("[AES256ImportKeyOpts] Invalid Key Length [%d]. Must be 32 bytes", len(aesRaw))
234-
}
235-
236-
aesK := &aesPrivateKey{utils.Clone(aesRaw), false}
237-
238-
// If the key is not Ephemeral, store it.
239-
if !opts.Ephemeral() {
240-
// Store the key
241-
err = csp.ks.StoreKey(aesK)
242-
if err != nil {
243-
return nil, fmt.Errorf("Failed storing AES key [%s]", err)
244-
}
245-
}
246-
247-
return aesK, nil
248-
249-
case *bccsp.HMACImportKeyOpts:
250-
aesRaw, ok := raw.([]byte)
251-
if !ok {
252-
return nil, errors.New("[HMACImportKeyOpts] Invalid raw material. Expected byte array.")
253-
}
254-
255-
if len(aesRaw) == 0 {
256-
return nil, errors.New("[HMACImportKeyOpts] Invalid raw. It must not be nil.")
257-
}
258-
259-
aesK := &aesPrivateKey{utils.Clone(aesRaw), false}
260-
261-
// If the key is not Ephemeral, store it.
262-
if !opts.Ephemeral() {
263-
// Store the key
264-
err = csp.ks.StoreKey(aesK)
265-
if err != nil {
266-
return nil, fmt.Errorf("Failed storing AES key [%s]", err)
267-
}
268-
}
269-
270-
return aesK, nil
271-
272-
case *bccsp.ECDSAPKIXPublicKeyImportOpts:
273-
der, ok := raw.([]byte)
274-
if !ok {
275-
return nil, errors.New("[ECDSAPKIXPublicKeyImportOpts] Invalid raw material. Expected byte array.")
276-
}
277-
278-
if len(der) == 0 {
279-
return nil, errors.New("[ECDSAPKIXPublicKeyImportOpts] Invalid raw. It must not be nil.")
280-
}
281-
282-
lowLevelKey, err := utils.DERToPublicKey(der)
283-
if err != nil {
284-
return nil, fmt.Errorf("Failed converting PKIX to ECDSA public key [%s]", err)
285-
}
286-
287-
ecdsaPK, ok := lowLevelKey.(*ecdsa.PublicKey)
288-
if !ok {
289-
return nil, errors.New("Failed casting to ECDSA public key. Invalid raw material.")
290-
}
291-
292-
k = &ecdsaPublicKey{ecdsaPK}
293-
294-
// If the key is not Ephemeral, store it.
295-
if !opts.Ephemeral() {
296-
// Store the key
297-
err = csp.ks.StoreKey(k)
298-
if err != nil {
299-
return nil, fmt.Errorf("Failed storing ECDSA key [%s]", err)
300-
}
301-
}
302-
303-
return k, nil
304-
305-
case *bccsp.ECDSAPrivateKeyImportOpts:
306-
der, ok := raw.([]byte)
307-
if !ok {
308-
return nil, errors.New("[ECDSADERPrivateKeyImportOpts] Invalid raw material. Expected byte array.")
309-
}
231+
keyImporter, found := csp.keyImporters[reflect.TypeOf(opts)]
232+
if !found {
233+
return nil, fmt.Errorf("Unsupported 'KeyImportOpts' provided [%v]", opts)
234+
}
310235

311-
if len(der) == 0 {
312-
return nil, errors.New("[ECDSADERPrivateKeyImportOpts] Invalid raw. It must not be nil.")
313-
}
236+
k, err = keyImporter.KeyImport(raw, opts)
237+
if err != nil {
238+
return nil, err
239+
}
314240

315-
lowLevelKey, err := utils.DERToPrivateKey(der)
241+
// If the key is not Ephemeral, store it.
242+
if !opts.Ephemeral() {
243+
// Store the key
244+
err = csp.ks.StoreKey(k)
316245
if err != nil {
317-
return nil, fmt.Errorf("Failed converting PKIX to ECDSA public key [%s]", err)
318-
}
319-
320-
ecdsaSK, ok := lowLevelKey.(*ecdsa.PrivateKey)
321-
if !ok {
322-
return nil, errors.New("Failed casting to ECDSA public key. Invalid raw material.")
323-
}
324-
325-
k = &ecdsaPrivateKey{ecdsaSK}
326-
327-
// If the key is not Ephemeral, store it.
328-
if !opts.Ephemeral() {
329-
// Store the key
330-
err = csp.ks.StoreKey(k)
331-
if err != nil {
332-
return nil, fmt.Errorf("Failed storing ECDSA key [%s]", err)
333-
}
334-
}
335-
336-
return k, nil
337-
338-
case *bccsp.ECDSAGoPublicKeyImportOpts:
339-
lowLevelKey, ok := raw.(*ecdsa.PublicKey)
340-
if !ok {
341-
return nil, errors.New("[ECDSAGoPublicKeyImportOpts] Invalid raw material. Expected *ecdsa.PublicKey.")
342-
}
343-
344-
k = &ecdsaPublicKey{lowLevelKey}
345-
346-
// If the key is not Ephemeral, store it.
347-
if !opts.Ephemeral() {
348-
// Store the key
349-
err = csp.ks.StoreKey(k)
350-
if err != nil {
351-
return nil, fmt.Errorf("Failed storing ECDSA key [%s]", err)
352-
}
353-
}
354-
355-
return k, nil
356-
357-
case *bccsp.RSAGoPublicKeyImportOpts:
358-
lowLevelKey, ok := raw.(*rsa.PublicKey)
359-
if !ok {
360-
return nil, errors.New("[RSAGoPublicKeyImportOpts] Invalid raw material. Expected *rsa.PublicKey.")
361-
}
362-
363-
k = &rsaPublicKey{lowLevelKey}
364-
365-
// If the key is not Ephemeral, store it.
366-
if !opts.Ephemeral() {
367-
// Store the key
368-
err = csp.ks.StoreKey(k)
369-
if err != nil {
370-
return nil, fmt.Errorf("Failed storing RSA publi key [%s]", err)
371-
}
372-
}
373-
374-
return k, nil
375-
376-
case *bccsp.X509PublicKeyImportOpts:
377-
x509Cert, ok := raw.(*x509.Certificate)
378-
if !ok {
379-
return nil, errors.New("[X509PublicKeyImportOpts] Invalid raw material. Expected *x509.Certificate.")
380-
}
381-
382-
pk := x509Cert.PublicKey
383-
384-
switch pk.(type) {
385-
case *ecdsa.PublicKey:
386-
return csp.KeyImport(pk, &bccsp.ECDSAGoPublicKeyImportOpts{Temporary: opts.Ephemeral()})
387-
case *rsa.PublicKey:
388-
return csp.KeyImport(pk, &bccsp.RSAGoPublicKeyImportOpts{Temporary: opts.Ephemeral()})
389-
default:
390-
return nil, errors.New("Certificate public key type not recognized. Supported keys: [ECDSA, RSA]")
246+
return nil, fmt.Errorf("Failed storing key [%s]. [%s]", opts.Algorithm(), err)
391247
}
392-
393-
default:
394-
return nil, fmt.Errorf("Unsupported 'KeyImportOptions' provided [%v]", opts)
395248
}
249+
250+
return k, nil
396251
}
397252

398253
// GetKey returns the key this CSP associates to

bccsp/sw/internals.go

+8
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ type KeyDeriver interface {
3737
KeyDeriv(k bccsp.Key, opts bccsp.KeyDerivOpts) (dk bccsp.Key, err error)
3838
}
3939

40+
// KeyImporter is a BCCSP-like interface that provides key import algorithms
41+
type KeyImporter interface {
42+
43+
// KeyImport imports a key from its raw representation using opts.
44+
// The opts argument should be appropriate for the primitive used.
45+
KeyImport(raw interface{}, opts bccsp.KeyImportOpts) (k bccsp.Key, err error)
46+
}
47+
4048
// Encryptor is a BCCSP-like interface that provides encryption algorithms
4149
type Encryptor interface {
4250

0 commit comments

Comments
 (0)