Skip to content

Commit 1109d63

Browse files
committed
[FAB-3441] bccsp/sw KeyDeriv test coverage
Using the approach discussed in FAB-3465, this change-sets refactors the way key derivation 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 85% Change-Id: I29f460830ac9531755c5b818b222b75339a75f8b Signed-off-by: Angelo De Caro <[email protected]>
1 parent a3665e3 commit 1109d63

File tree

7 files changed

+361
-197
lines changed

7 files changed

+361
-197
lines changed

bccsp/mocks/mocks.go

+12
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,15 @@ type HashOpts struct{}
170170
func (HashOpts) Algorithm() string {
171171
return "Mock HashOpts"
172172
}
173+
174+
type KeyDerivOpts struct {
175+
EphemeralValue bool
176+
}
177+
178+
func (*KeyDerivOpts) Algorithm() string {
179+
return "Mock KeyDerivOpts"
180+
}
181+
182+
func (o *KeyDerivOpts) Ephemeral() bool {
183+
return o.EphemeralValue
184+
}

bccsp/sw/impl.go

+27-171
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,11 @@ package sw
1818
import (
1919
"crypto/ecdsa"
2020
"crypto/elliptic"
21-
"crypto/hmac"
2221
"crypto/rsa"
2322
"crypto/x509"
2423
"errors"
2524
"fmt"
2625
"hash"
27-
"math/big"
2826
"reflect"
2927

3028
"crypto/sha256"
@@ -125,6 +123,13 @@ func New(securityLevel int, hashFamily string, keyStore bccsp.KeyStore) (bccsp.B
125123
keyGenerators[reflect.TypeOf(&bccsp.RSA4096KeyGenOpts{})] = &rsaKeyGenerator{length: 4096}
126124
impl.keyGenerators = keyGenerators
127125

126+
// Set the key generators
127+
keyDerivers := make(map[reflect.Type]KeyDeriver)
128+
keyDerivers[reflect.TypeOf(&ecdsaPrivateKey{})] = &ecdsaPrivateKeyKeyDeriver{}
129+
keyDerivers[reflect.TypeOf(&ecdsaPublicKey{})] = &ecdsaPublicKeyKeyDeriver{}
130+
keyDerivers[reflect.TypeOf(&aesPrivateKey{})] = &aesPrivateKeyKeyDeriver{bccsp: impl}
131+
impl.keyDerivers = keyDerivers
132+
128133
return impl, nil
129134
}
130135

@@ -134,6 +139,7 @@ type impl struct {
134139
ks bccsp.KeyStore
135140

136141
keyGenerators map[reflect.Type]KeyGenerator
142+
keyDerivers map[reflect.Type]KeyDeriver
137143
encryptors map[reflect.Type]Encryptor
138144
decryptors map[reflect.Type]Decryptor
139145
signers map[reflect.Type]Signer
@@ -177,180 +183,30 @@ func (csp *impl) KeyDeriv(k bccsp.Key, opts bccsp.KeyDerivOpts) (dk bccsp.Key, e
177183
if k == nil {
178184
return nil, errors.New("Invalid Key. It must not be nil.")
179185
}
186+
if opts == nil {
187+
return nil, errors.New("Invalid opts. It must not be nil.")
188+
}
180189

181-
// Derive key
182-
switch k.(type) {
183-
case *ecdsaPublicKey:
184-
// Validate opts
185-
if opts == nil {
186-
return nil, errors.New("Invalid Opts parameter. It must not be nil.")
187-
}
188-
189-
ecdsaK := k.(*ecdsaPublicKey)
190-
191-
switch opts.(type) {
192-
193-
// Re-randomized an ECDSA private key
194-
case *bccsp.ECDSAReRandKeyOpts:
195-
reRandOpts := opts.(*bccsp.ECDSAReRandKeyOpts)
196-
tempSK := &ecdsa.PublicKey{
197-
Curve: ecdsaK.pubKey.Curve,
198-
X: new(big.Int),
199-
Y: new(big.Int),
200-
}
201-
202-
var k = new(big.Int).SetBytes(reRandOpts.ExpansionValue())
203-
var one = new(big.Int).SetInt64(1)
204-
n := new(big.Int).Sub(ecdsaK.pubKey.Params().N, one)
205-
k.Mod(k, n)
206-
k.Add(k, one)
207-
208-
// Compute temporary public key
209-
tempX, tempY := ecdsaK.pubKey.ScalarBaseMult(k.Bytes())
210-
tempSK.X, tempSK.Y = tempSK.Add(
211-
ecdsaK.pubKey.X, ecdsaK.pubKey.Y,
212-
tempX, tempY,
213-
)
214-
215-
// Verify temporary public key is a valid point on the reference curve
216-
isOn := tempSK.Curve.IsOnCurve(tempSK.X, tempSK.Y)
217-
if !isOn {
218-
return nil, errors.New("Failed temporary public key IsOnCurve check.")
219-
}
220-
221-
reRandomizedKey := &ecdsaPublicKey{tempSK}
222-
223-
// If the key is not Ephemeral, store it.
224-
if !opts.Ephemeral() {
225-
// Store the key
226-
err = csp.ks.StoreKey(reRandomizedKey)
227-
if err != nil {
228-
return nil, fmt.Errorf("Failed storing ECDSA key [%s]", err)
229-
}
230-
}
231-
232-
return reRandomizedKey, nil
233-
234-
default:
235-
return nil, fmt.Errorf("Unrecognized KeyDerivOpts provided [%s]", opts.Algorithm())
236-
237-
}
238-
case *ecdsaPrivateKey:
239-
// Validate opts
240-
if opts == nil {
241-
return nil, errors.New("Invalid Opts parameter. It must not be nil.")
242-
}
243-
244-
ecdsaK := k.(*ecdsaPrivateKey)
245-
246-
switch opts.(type) {
247-
248-
// Re-randomized an ECDSA private key
249-
case *bccsp.ECDSAReRandKeyOpts:
250-
reRandOpts := opts.(*bccsp.ECDSAReRandKeyOpts)
251-
tempSK := &ecdsa.PrivateKey{
252-
PublicKey: ecdsa.PublicKey{
253-
Curve: ecdsaK.privKey.Curve,
254-
X: new(big.Int),
255-
Y: new(big.Int),
256-
},
257-
D: new(big.Int),
258-
}
259-
260-
var k = new(big.Int).SetBytes(reRandOpts.ExpansionValue())
261-
var one = new(big.Int).SetInt64(1)
262-
n := new(big.Int).Sub(ecdsaK.privKey.Params().N, one)
263-
k.Mod(k, n)
264-
k.Add(k, one)
265-
266-
tempSK.D.Add(ecdsaK.privKey.D, k)
267-
tempSK.D.Mod(tempSK.D, ecdsaK.privKey.PublicKey.Params().N)
268-
269-
// Compute temporary public key
270-
tempX, tempY := ecdsaK.privKey.PublicKey.ScalarBaseMult(k.Bytes())
271-
tempSK.PublicKey.X, tempSK.PublicKey.Y =
272-
tempSK.PublicKey.Add(
273-
ecdsaK.privKey.PublicKey.X, ecdsaK.privKey.PublicKey.Y,
274-
tempX, tempY,
275-
)
276-
277-
// Verify temporary public key is a valid point on the reference curve
278-
isOn := tempSK.Curve.IsOnCurve(tempSK.PublicKey.X, tempSK.PublicKey.Y)
279-
if !isOn {
280-
return nil, errors.New("Failed temporary public key IsOnCurve check.")
281-
}
282-
283-
reRandomizedKey := &ecdsaPrivateKey{tempSK}
284-
285-
// If the key is not Ephemeral, store it.
286-
if !opts.Ephemeral() {
287-
// Store the key
288-
err = csp.ks.StoreKey(reRandomizedKey)
289-
if err != nil {
290-
return nil, fmt.Errorf("Failed storing ECDSA key [%s]", err)
291-
}
292-
}
293-
294-
return reRandomizedKey, nil
295-
296-
default:
297-
return nil, fmt.Errorf("Unrecognized KeyDerivOpts provided [%s]", opts.Algorithm())
298-
299-
}
300-
case *aesPrivateKey:
301-
// Validate opts
302-
if opts == nil {
303-
return nil, errors.New("Invalid Opts parameter. It must not be nil.")
304-
}
305-
306-
aesK := k.(*aesPrivateKey)
307-
308-
switch opts.(type) {
309-
case *bccsp.HMACTruncated256AESDeriveKeyOpts:
310-
hmacOpts := opts.(*bccsp.HMACTruncated256AESDeriveKeyOpts)
311-
312-
mac := hmac.New(csp.conf.hashFunction, aesK.privKey)
313-
mac.Write(hmacOpts.Argument())
314-
hmacedKey := &aesPrivateKey{mac.Sum(nil)[:csp.conf.aesBitLength], false}
315-
316-
// If the key is not Ephemeral, store it.
317-
if !opts.Ephemeral() {
318-
// Store the key
319-
err = csp.ks.StoreKey(hmacedKey)
320-
if err != nil {
321-
return nil, fmt.Errorf("Failed storing ECDSA key [%s]", err)
322-
}
323-
}
324-
325-
return hmacedKey, nil
326-
327-
case *bccsp.HMACDeriveKeyOpts:
328-
329-
hmacOpts := opts.(*bccsp.HMACDeriveKeyOpts)
330-
331-
mac := hmac.New(csp.conf.hashFunction, aesK.privKey)
332-
mac.Write(hmacOpts.Argument())
333-
hmacedKey := &aesPrivateKey{mac.Sum(nil), true}
334-
335-
// If the key is not Ephemeral, store it.
336-
if !opts.Ephemeral() {
337-
// Store the key
338-
err = csp.ks.StoreKey(hmacedKey)
339-
if err != nil {
340-
return nil, fmt.Errorf("Failed storing ECDSA key [%s]", err)
341-
}
342-
}
343-
344-
return hmacedKey, nil
190+
keyDeriver, found := csp.keyDerivers[reflect.TypeOf(k)]
191+
if !found {
192+
return nil, fmt.Errorf("Unsupported 'Key' provided [%v]", k)
193+
}
345194

346-
default:
347-
return nil, fmt.Errorf("Unrecognized KeyDerivOpts provided [%s]", opts.Algorithm())
195+
k, err = keyDeriver.KeyDeriv(k, opts)
196+
if err != nil {
197+
return nil, err
198+
}
348199

200+
// If the key is not Ephemeral, store it.
201+
if !opts.Ephemeral() {
202+
// Store the key
203+
err = csp.ks.StoreKey(k)
204+
if err != nil {
205+
return nil, fmt.Errorf("Failed storing key [%s]. [%s]", opts.Algorithm(), err)
349206
}
350-
351-
default:
352-
return nil, fmt.Errorf("Key type not recognized [%s]", k)
353207
}
208+
209+
return k, nil
354210
}
355211

356212
// KeyImport imports a key from its raw representation using opts.

bccsp/sw/internals.go

+8
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ type KeyGenerator interface {
2929
KeyGen(opts bccsp.KeyGenOpts) (k bccsp.Key, err error)
3030
}
3131

32+
// KeyDeriver is a BCCSP-like interface that provides key derivation algorithms
33+
type KeyDeriver interface {
34+
35+
// KeyDeriv derives a key from k using opts.
36+
// The opts argument should be appropriate for the primitive used.
37+
KeyDeriv(k bccsp.Key, opts bccsp.KeyDerivOpts) (dk bccsp.Key, err error)
38+
}
39+
3240
// Encryptor is a BCCSP-like interface that provides encryption algorithms
3341
type Encryptor interface {
3442

0 commit comments

Comments
 (0)