Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Commit 5cecd16

Browse files
sudeshrshettytroyronda
authored andcommitted
[FAB-11135] Add cache for pkcs11 object handle
Change-Id: I171aac72cc09cd5baab76b4410e4418ec138f5fe Signed-off-by: Firas Qutishat <firas.qutishat@securekey.com> Signed-off-by: Sudesh Shetty <sudesh.shetty@securekey.com>
1 parent 93590f0 commit 5cecd16

File tree

3 files changed

+176
-34
lines changed

3 files changed

+176
-34
lines changed

internal/github.com/hyperledger/fabric/bccsp/pkcs11/impl.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,13 @@ import (
2828
"math/big"
2929
"os"
3030

31+
"sync"
32+
3133
"github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/bccsp"
3234
"github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/bccsp/sw"
3335
"github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/bccsp/utils"
3436
flogging "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/sdkpatch/logbridge"
37+
"github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/sdkpatch/sessioncache"
3538
"github.com/miekg/pkcs11"
3639
"github.com/pkg/errors"
3740
)
@@ -71,8 +74,10 @@ func New(opts PKCS11Opts, keyStore bccsp.KeyStore) (bccsp.BCCSP, error) {
7174
}
7275

7376
sessions := make(chan pkcs11.SessionHandle, sessionCacheSize)
74-
csp := &impl{swCSP, conf, keyStore, ctx, sessions, slot, lib, opts.Sensitive, opts.SoftVerify}
77+
csp := &impl{BCCSP: swCSP, conf: conf, ks: keyStore, ctx: ctx, sessions: sessions, slot: slot, lib: lib, noPrivImport: opts.Sensitive, softVerify: opts.SoftVerify}
7578
csp.returnSession(*session)
79+
sessioncache.ClearAllSession(csp.rwMtx)
80+
7681
return csp, nil
7782
}
7883

@@ -89,6 +94,7 @@ type impl struct {
8994
lib string
9095
noPrivImport bool
9196
softVerify bool
97+
rwMtx sync.RWMutex
9298
}
9399

94100
// KeyGen generates a key using opts.

internal/github.com/hyperledger/fabric/bccsp/pkcs11/pkcs11.go

Lines changed: 20 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ import (
2020
"math/big"
2121
"sync"
2222

23+
"time"
24+
2325
logging "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/sdkpatch/logbridge"
26+
"github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/sdkpatch/sessioncache"
2427
"github.com/miekg/pkcs11"
2528
)
2629

@@ -107,7 +110,11 @@ func (csp *impl) getSession() (session pkcs11.SessionHandle) {
107110
}
108111
logger.Debugf("Created new pkcs11 session %+v on slot %d\n", s, csp.slot)
109112
session = s
113+
sessioncache.ClearSession(csp.rwMtx, fmt.Sprintf("%d", session))
110114
}
115+
116+
sessioncache.AddSession(csp.rwMtx, fmt.Sprintf("%d", session))
117+
111118
return session
112119
}
113120

@@ -128,13 +135,13 @@ func (csp *impl) getECKey(ski []byte) (pubKey *ecdsa.PublicKey, isPriv bool, err
128135
session := csp.getSession()
129136
defer csp.returnSession(session)
130137
isPriv = true
131-
_, err = findKeyPairFromSKI(p11lib, session, ski, privateKeyFlag)
138+
_, err = csp.findKeyPairFromSKI(p11lib, session, ski, privateKeyFlag)
132139
if err != nil {
133140
isPriv = false
134141
logger.Debugf("Private key not found [%s] for SKI [%s], looking for Public key", err, hex.EncodeToString(ski))
135142
}
136143

137-
publicKey, err := findKeyPairFromSKI(p11lib, session, ski, publicKeyFlag)
144+
publicKey, err := csp.findKeyPairFromSKI(p11lib, session, ski, publicKeyFlag)
138145
if err != nil {
139146
return nil, false, fmt.Errorf("Public key not found [%s] for SKI [%s]", err, hex.EncodeToString(ski))
140147
}
@@ -306,7 +313,8 @@ func (csp *impl) signP11ECDSA(ski []byte, msg []byte) (R, S *big.Int, err error)
306313
session := csp.getSession()
307314
defer csp.returnSession(session)
308315

309-
privateKey, err := findKeyPairFromSKI(p11lib, session, ski, privateKeyFlag)
316+
privateKey, err := csp.findKeyPairFromSKI(p11lib, session, ski, privateKeyFlag)
317+
defer timeTrack(time.Now(), fmt.Sprintf("signing [session: %d]", session))
310318
if err != nil {
311319
return nil, nil, fmt.Errorf("Private key not found [%s]\n", err)
312320
}
@@ -338,7 +346,7 @@ func (csp *impl) verifyP11ECDSA(ski []byte, msg []byte, R, S *big.Int, byteSize
338346

339347
logger.Debugf("Verify ECDSA\n")
340348

341-
publicKey, err := findKeyPairFromSKI(p11lib, session, ski, publicKeyFlag)
349+
publicKey, err := csp.findKeyPairFromSKI(p11lib, session, ski, publicKeyFlag)
342350
if err != nil {
343351
return false, fmt.Errorf("Public key not found [%s]\n", err)
344352
}
@@ -442,34 +450,8 @@ const (
442450
publicKeyFlag = false
443451
)
444452

445-
func findKeyPairFromSKI(mod *pkcs11.Ctx, session pkcs11.SessionHandle, ski []byte, keyType bool) (*pkcs11.ObjectHandle, error) {
446-
ktype := pkcs11.CKO_PUBLIC_KEY
447-
if keyType == privateKeyFlag {
448-
ktype = pkcs11.CKO_PRIVATE_KEY
449-
}
450-
451-
template := []*pkcs11.Attribute{
452-
pkcs11.NewAttribute(pkcs11.CKA_CLASS, ktype),
453-
pkcs11.NewAttribute(pkcs11.CKA_ID, ski),
454-
}
455-
if err := mod.FindObjectsInit(session, template); err != nil {
456-
return nil, err
457-
}
458-
459-
// single session instance, assume one hit only
460-
objs, _, err := mod.FindObjects(session, 1)
461-
if err != nil {
462-
return nil, err
463-
}
464-
if err = mod.FindObjectsFinal(session); err != nil {
465-
return nil, err
466-
}
467-
468-
if len(objs) == 0 {
469-
return nil, fmt.Errorf("Key not found [%s]", hex.Dump(ski))
470-
}
471-
472-
return &objs[0], nil
453+
func (csp *impl) findKeyPairFromSKI(mod *pkcs11.Ctx, session pkcs11.SessionHandle, ski []byte, keyType bool) (*pkcs11.ObjectHandle, error) {
454+
return sessioncache.GetKeyPairFromSessionSKI(csp.rwMtx, &sessioncache.KeyPairCacheKey{Mod: mod, Session: session, SKI: ski, KeyType: keyType})
473455
}
474456

475457
// Fairly straightforward EC-point query, other than opencryptoki
@@ -585,7 +567,7 @@ func (csp *impl) getSecretValue(ski []byte) []byte {
585567
session := csp.getSession()
586568
defer csp.returnSession(session)
587569

588-
keyHandle, err := findKeyPairFromSKI(p11lib, session, ski, privateKeyFlag)
570+
keyHandle, err := csp.findKeyPairFromSKI(p11lib, session, ski, privateKeyFlag)
589571

590572
var privKey []byte
591573
template := []*pkcs11.Attribute{
@@ -619,3 +601,8 @@ func nextIDCtr() *big.Int {
619601
id_mutex.Unlock()
620602
return id_ctr
621603
}
604+
605+
func timeTrack(start time.Time, msg string) {
606+
elapsed := time.Since(start)
607+
logger.Debugf("%s took %s", msg, elapsed)
608+
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/*
2+
Copyright SecureKey Technologies Inc. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
/*
7+
Notice: This file has been modified for Hyperledger Fabric SDK Go usage.
8+
Please review third_party pinning scripts and patches for more details.
9+
*/
10+
11+
package sessioncache
12+
13+
import (
14+
"fmt"
15+
"time"
16+
17+
"sync"
18+
19+
"encoding/hex"
20+
21+
flogging "github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/sdkpatch/logbridge"
22+
"github.com/hyperledger/fabric-sdk-go/pkg/util/concurrent/lazycache"
23+
"github.com/hyperledger/fabric-sdk-go/pkg/util/concurrent/lazyref"
24+
"github.com/miekg/pkcs11"
25+
)
26+
27+
var sessionCache map[string]*lazycache.Cache
28+
29+
var logger = flogging.MustGetLogger("bccsp_p11_sessioncache")
30+
31+
const (
32+
privateKeyFlag = true
33+
)
34+
35+
// keyPairCacheKey
36+
type KeyPairCacheKey struct {
37+
Mod *pkcs11.Ctx
38+
Session pkcs11.SessionHandle
39+
SKI []byte
40+
KeyType bool
41+
}
42+
43+
//String return string value for config key
44+
func (keyPairCacheKey *KeyPairCacheKey) String() string {
45+
return fmt.Sprintf("%x_%t", keyPairCacheKey.SKI, keyPairCacheKey.KeyType)
46+
}
47+
48+
func timeTrack(start time.Time, msg string) {
49+
elapsed := time.Since(start)
50+
logger.Debugf("%s took %s", msg, elapsed)
51+
}
52+
53+
func ClearAllSession(rwMtx sync.RWMutex) {
54+
55+
if sessionCache != nil && len(sessionCache) > 0 {
56+
rwMtx.Lock()
57+
for _, val := range sessionCache {
58+
val.Close()
59+
}
60+
sessionCache = nil
61+
rwMtx.Unlock()
62+
}
63+
}
64+
65+
func ClearSession(rwMtx sync.RWMutex, key string) {
66+
rwMtx.RLock()
67+
val, ok := sessionCache[key]
68+
rwMtx.RUnlock()
69+
if ok {
70+
rwMtx.Lock()
71+
val.Close()
72+
sessionCache[key] = nil
73+
rwMtx.Unlock()
74+
75+
}
76+
}
77+
78+
func AddSession(rwMtx sync.RWMutex, key string) {
79+
rwMtx.RLock()
80+
_, ok := sessionCache[key]
81+
rwMtx.RUnlock()
82+
83+
if !ok {
84+
if sessionCache == nil {
85+
sessionCache = make(map[string]*lazycache.Cache)
86+
}
87+
rwMtx.Lock()
88+
sessionCache[key] = lazycache.New(
89+
"KeyPair_Resolver_Cache",
90+
func(key lazycache.Key) (interface{}, error) {
91+
return lazyref.New(
92+
func() (interface{}, error) {
93+
return getKeyPairFromSKI(key.(*KeyPairCacheKey))
94+
},
95+
), nil
96+
})
97+
rwMtx.Unlock()
98+
}
99+
}
100+
101+
func GetKeyPairFromSessionSKI(rwMtx sync.RWMutex, keyPairCacheKey *KeyPairCacheKey) (*pkcs11.ObjectHandle, error) {
102+
rwMtx.RLock()
103+
val, ok := sessionCache[fmt.Sprintf("%d", keyPairCacheKey.Session)]
104+
rwMtx.RUnlock()
105+
if ok {
106+
defer timeTrack(time.Now(), fmt.Sprintf("finding key [session: %d] [ski: %x]", keyPairCacheKey.Session, keyPairCacheKey.SKI))
107+
value, err := val.Get(keyPairCacheKey)
108+
if err != nil {
109+
return nil, err
110+
}
111+
lazyRef := value.(*lazyref.Reference)
112+
resolver, err := lazyRef.Get()
113+
if err != nil {
114+
return nil, err
115+
}
116+
return resolver.(*pkcs11.ObjectHandle), nil
117+
}
118+
return nil, fmt.Errorf("cannot find session in sessionCache")
119+
}
120+
121+
func getKeyPairFromSKI(keyPairCacheKey *KeyPairCacheKey) (*pkcs11.ObjectHandle, error) {
122+
ktype := pkcs11.CKO_PUBLIC_KEY
123+
if keyPairCacheKey.KeyType == privateKeyFlag {
124+
ktype = pkcs11.CKO_PRIVATE_KEY
125+
}
126+
127+
template := []*pkcs11.Attribute{
128+
pkcs11.NewAttribute(pkcs11.CKA_CLASS, ktype),
129+
pkcs11.NewAttribute(pkcs11.CKA_ID, keyPairCacheKey.SKI),
130+
}
131+
if err := keyPairCacheKey.Mod.FindObjectsInit(keyPairCacheKey.Session, template); err != nil {
132+
return nil, err
133+
}
134+
135+
// single session instance, assume one hit only
136+
objs, _, err := keyPairCacheKey.Mod.FindObjects(keyPairCacheKey.Session, 1)
137+
if err != nil {
138+
return nil, err
139+
}
140+
if err = keyPairCacheKey.Mod.FindObjectsFinal(keyPairCacheKey.Session); err != nil {
141+
return nil, err
142+
}
143+
144+
if len(objs) == 0 {
145+
return nil, fmt.Errorf("Key not found [%s]", hex.Dump(keyPairCacheKey.SKI))
146+
}
147+
148+
return &objs[0], nil
149+
}

0 commit comments

Comments
 (0)