Skip to content

Commit

Permalink
feat: apis to create keys in wallet kms
Browse files Browse the repository at this point in the history
-EDV encryption & MAC key IDs cannot be passed as profile settings for
localkms users since wallet creates local kms internally based on user's
secret lock service. So wallet has to expose an API to generate EDV keys
in wallet kms.
- Closes hyperledger-archives#2768

Signed-off-by: sudesh.shetty <sudesh.shetty@securekey.com>
  • Loading branch information
sudeshrshetty committed Apr 29, 2021
1 parent a595aa0 commit ce328a9
Show file tree
Hide file tree
Showing 8 changed files with 250 additions and 78 deletions.
5 changes: 5 additions & 0 deletions pkg/mock/kms/mock_kms.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type KeyManager struct {
CreateKeyID string
CreateKeyValue *keyset.Handle
CreateKeyErr error
CreateKeyFn func(kt kmsservice.KeyType) (string, interface{}, error)
GetKeyValue *keyset.Handle
GetKeyErr error
RotateKeyID string
Expand All @@ -47,6 +48,10 @@ func (k *KeyManager) Create(kt kmsservice.KeyType) (string, interface{}, error)
return "", nil, k.CreateKeyErr
}

if k.CreateKeyFn != nil {
return k.CreateKeyFn(kt)
}

return k.CreateKeyID, k.CreateKeyValue, nil
}

Expand Down
10 changes: 8 additions & 2 deletions pkg/wallet/contents_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,15 @@ func TestContentStores(t *testing.T) {
require.NoError(t, err)
require.NotEmpty(t, tkn)

ok, err := profileInfo.setupEDVKeys(tkn, "", "")
kmgr, err := keyManager().getKeyManger(tkn)
require.NoError(t, err)
require.NotEmpty(t, kmgr)

err = profileInfo.setupEDVEncryptionKey(kmgr)
require.NoError(t, err)

err = profileInfo.setupEDVMacKey(kmgr)
require.NoError(t, err)
require.True(t, ok)

// create new store
contentStore := newContentStore(sp, profileInfo)
Expand Down
49 changes: 13 additions & 36 deletions pkg/wallet/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func (pr *profile) setEDVOptions(opts *edvConf) error {
return nil
}

if opts.ServerURL == "" || opts.VaultID == "" || opts.EncryptionKeyID == "" || opts.MACKeyID == "" {
if opts.ServerURL == "" || opts.VaultID == "" {
return errors.New("invalid EDV settings in profile")
}

Expand All @@ -124,49 +124,26 @@ func (pr *profile) setEDVOptions(opts *edvConf) error {
return nil
}

// nolint:gocyclo
func (pr *profile) setupEDVKeys(auth string, encryptionKeyType, macKeyType kms.KeyType) (bool, error) {
setupEncKey := pr.EDVConf != nil && pr.EDVConf.EncryptionKeyID == ""
setupMacKey := pr.EDVConf != nil && pr.EDVConf.MACKeyID == ""

if !(setupEncKey || setupMacKey) {
return false, nil
}

keyMgr, err := keyManager().getKeyManger(auth)
func (pr *profile) setupEDVEncryptionKey(keyManager kms.KeyManager) error {
kid, _, err := keyManager.Create(kms.NISTP256ECDHKWType)
if err != nil {
return false, err
return err
}

// if encryption key is not yet setup then create one and set.
if setupEncKey {
if encryptionKeyType == "" {
encryptionKeyType = kms.NISTP256ECDHKWType
}
pr.EDVConf.EncryptionKeyID = kid

kid, _, err := keyMgr.Create(encryptionKeyType)
if err != nil {
return false, err
}
return nil
}

pr.EDVConf.EncryptionKeyID = kid
func (pr *profile) setupEDVMacKey(keyManager kms.KeyManager) error {
kid, _, err := keyManager.Create(kms.HMACSHA256Tag256Type)
if err != nil {
return err
}

// if MAC key is not yet setup then create one and set.
if setupMacKey {
if macKeyType == "" {
macKeyType = kms.HMACSHA256Tag256Type
}
pr.EDVConf.MACKeyID = kid

kid, _, err := keyMgr.Create(macKeyType)
if err != nil {
return false, err
}

pr.EDVConf.MACKeyID = kid
}

return true, nil
return nil
}

func (pr *profile) resetKMSOptions() {
Expand Down
26 changes: 5 additions & 21 deletions pkg/wallet/profile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"github.com/google/uuid"
"github.com/stretchr/testify/require"

kmsapi "github.com/hyperledger/aries-framework-go/pkg/kms"
mockkms "github.com/hyperledger/aries-framework-go/pkg/mock/kms"
"github.com/hyperledger/aries-framework-go/pkg/mock/secretlock"
mockstorage "github.com/hyperledger/aries-framework-go/pkg/mock/storage"
Expand Down Expand Up @@ -136,37 +135,22 @@ func TestCreateNewProfile(t *testing.T) {
require.NoError(t, keyManager().saveKeyManger(uuid.New().String(), token, kms, 500*time.Millisecond))

// setup edv keys
ok, err := sampleProfile.setupEDVKeys(token, kmsapi.NISTP256ECDHKWType, kmsapi.HMACSHA256Tag256Type)
err := sampleProfile.setupEDVEncryptionKey(&mockkms.KeyManager{CreateKeyID: kid})
require.NoError(t, err)
require.True(t, ok)
require.Equal(t, sampleProfile.EDVConf.EncryptionKeyID, kid)
require.Equal(t, sampleProfile.EDVConf.MACKeyID, kid)

// no update
ok, err = sampleProfile.setupEDVKeys(token, "", "")
err = sampleProfile.setupEDVMacKey(&mockkms.KeyManager{CreateKeyID: kid})
require.NoError(t, err)
require.False(t, ok)
require.Equal(t, sampleProfile.EDVConf.MACKeyID, kid)

// test create key error
require.NoError(t, keyManager().saveKeyManger(uuid.New().String(), token,
&mockkms.KeyManager{CreateKeyErr: errors.New(sampleKeyMgrErr)}, 500*time.Millisecond))

sampleProfile.EDVConf.MACKeyID = ""
ok, err = sampleProfile.setupEDVKeys(token, "", "")
err = sampleProfile.setupEDVEncryptionKey(&mockkms.KeyManager{CreateKeyErr: errors.New(sampleKeyMgrErr)})
require.Error(t, err)
require.Contains(t, err.Error(), sampleKeyMgrErr)
require.False(t, ok)

sampleProfile.EDVConf.EncryptionKeyID = ""
ok, err = sampleProfile.setupEDVKeys(token, "", "")
err = sampleProfile.setupEDVMacKey(&mockkms.KeyManager{CreateKeyErr: errors.New(sampleKeyMgrErr)})
require.Error(t, err)
require.Contains(t, err.Error(), sampleKeyMgrErr)
require.False(t, ok)

// invalid auth
ok, err = sampleProfile.setupEDVKeys(token+"invalid", "", "")
require.Error(t, err)
require.False(t, ok)
})
}

Expand Down
4 changes: 4 additions & 0 deletions pkg/wallet/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ func (s *storageProvider) OpenStore(auth string, opts *unlockOpts, config storag
}

func createEDVStorageProvider(auth string, conf *edvConf, opts *unlockOpts) (storage.Provider, error) {
if conf.EncryptionKeyID == "" || conf.MACKeyID == "" {
return nil, errors.New("invalid EDV configuration found in wallet profile, key IDs for encryption and MAC operations are missing") //nolint: lll
}

// get key manager
keyMgr, err := keyManager().getKeyManger(auth)
if err != nil {
Expand Down
32 changes: 26 additions & 6 deletions pkg/wallet/storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,15 @@ func TestStorageProvider_OpenStore(t *testing.T) {
},
}

ok, err := sampleProfile.setupEDVKeys(token, "", "")
kmgr, err := keyManager().getKeyManger(token)
require.NoError(t, err)
require.NotEmpty(t, kmgr)

err = sampleProfile.setupEDVEncryptionKey(kmgr)
require.NoError(t, err)

err = sampleProfile.setupEDVMacKey(kmgr)
require.NoError(t, err)
require.True(t, ok)

wsp := newWalletStorageProvider(sampleProfile, nil)

Expand Down Expand Up @@ -96,14 +102,28 @@ func TestStorageProvider_OpenStore(t *testing.T) {
},
}

ok, err := sampleProfile.setupEDVKeys(token, "", "")
// invalid settings
wsp := newWalletStorageProvider(sampleProfile, nil)
store, err := wsp.OpenStore(token, &unlockOpts{},
storage.StoreConfiguration{TagNames: []string{Credential.Name()}})
require.Error(t, err)
require.Contains(t, err.Error(), "invalid EDV configuration found in wallet profile")
require.Empty(t, store)

kmgr, err := keyManager().getKeyManger(token)
require.NoError(t, err)
require.True(t, ok)
require.NotEmpty(t, kmgr)

wsp := newWalletStorageProvider(sampleProfile, nil)
err = sampleProfile.setupEDVEncryptionKey(kmgr)
require.NoError(t, err)

err = sampleProfile.setupEDVMacKey(kmgr)
require.NoError(t, err)

wsp = newWalletStorageProvider(sampleProfile, nil)

// invalid auth
store, err := wsp.OpenStore(token+".", &unlockOpts{},
store, err = wsp.OpenStore(token+".", &unlockOpts{},
storage.StoreConfiguration{TagNames: []string{Credential.Name()}})
require.Error(t, err)
require.True(t, errors.Is(err, ErrWalletLocked))
Expand Down
67 changes: 67 additions & 0 deletions pkg/wallet/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,52 @@ func UpdateProfile(userID string, ctx provider, options ...ProfileOptions) error
return createOrUpdate(userID, ctx, true, options...)
}

// CreateDataVaultKeyPairs can be used create EDV key pairs for given profile.
// Wallet will create key pairs in profile kms and updates profile with newly generate EDV encryption & MAC key IDs.
func CreateDataVaultKeyPairs(userID string, ctx provider, options ...UnlockOptions) error {
store, err := newProfileStore(ctx.StorageProvider())
if err != nil {
return fmt.Errorf("failed to get wallet user profile: failed to get store: %w", err)
}

profile, err := store.get(userID)
if err != nil {
return fmt.Errorf("failed to get wallet user profile: %w", err)
}

if profile.EDVConf == nil {
return fmt.Errorf("invalid operation, no edv configuration found in profile: %w", err)
}

opts := &unlockOpts{}

for _, opt := range options {
opt(opts)
}

// unlock key manager
token, err := keyManager().createKeyManager(profile, ctx.StorageProvider(), opts)
if err != nil {
return err
}

defer keyManager().removeKeyManager(userID)

// update profile
err = updateProfile(token, profile)
if err != nil {
return fmt.Errorf("failed to create key pairs: %w", err)
}

// update profile
err = store.save(profile, true)
if err != nil {
return fmt.Errorf("failed to update profile: %w", err)
}

return nil
}

func createOrUpdate(userID string, ctx provider, update bool, options ...ProfileOptions) error {
opts := &profileOpts{}

Expand Down Expand Up @@ -681,3 +727,24 @@ func addContext(v interface{}, context string) {
vc.Context = append(vc.Context, context)
}
}

func updateProfile(auth string, profile *profile) error {
// get key manager
keyManager, err := keyManager().getKeyManger(auth)
if err != nil {
return err
}

// setup key pairs
err = profile.setupEDVEncryptionKey(keyManager)
if err != nil {
return fmt.Errorf("failed to create EDV encryption key pair: %w", err)
}

err = profile.setupEDVMacKey(keyManager)
if err != nil {
return fmt.Errorf("failed to create EDV MAC key pair: %w", err)
}

return nil
}

0 comments on commit ce328a9

Please sign in to comment.