github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/bccsp/pkcs11/pkcs11.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package pkcs11
     8  
     9  import (
    10  	"crypto/ecdsa"
    11  	"crypto/elliptic"
    12  	"crypto/sha256"
    13  	"crypto/x509"
    14  	"encoding/asn1"
    15  	"encoding/hex"
    16  	"fmt"
    17  	"math/big"
    18  	"os"
    19  	"regexp"
    20  	"sync"
    21  	"time"
    22  
    23  	"github.com/miekg/pkcs11"
    24  	"github.com/osdi23p228/fabric/bccsp"
    25  	"github.com/osdi23p228/fabric/bccsp/sw"
    26  	"github.com/osdi23p228/fabric/common/flogging"
    27  	"github.com/pkg/errors"
    28  	"go.uber.org/zap/zapcore"
    29  )
    30  
    31  const createSessionRetries = 10
    32  
    33  var (
    34  	logger           = flogging.MustGetLogger("bccsp_p11")
    35  	regex            = regexp.MustCompile(".*0xB.:\\sCKR.+")
    36  	sessionCacheSize = 10
    37  )
    38  
    39  type impl struct {
    40  	bccsp.BCCSP
    41  
    42  	slot       uint
    43  	pin        string
    44  	ctx        *pkcs11.Ctx
    45  	conf       *config
    46  	softVerify bool
    47  	immutable  bool
    48  
    49  	sessLock sync.Mutex
    50  	sessPool chan pkcs11.SessionHandle
    51  	sessions map[pkcs11.SessionHandle]struct{}
    52  
    53  	cacheLock   sync.RWMutex
    54  	handleCache map[string]pkcs11.ObjectHandle
    55  	keyCache    map[string]bccsp.Key
    56  }
    57  
    58  // New WithParams returns a new instance of the software-based BCCSP
    59  // set at the passed security level, hash family and KeyStore.
    60  func New(opts PKCS11Opts, keyStore bccsp.KeyStore) (bccsp.BCCSP, error) {
    61  	// Init config
    62  	conf := &config{}
    63  	err := conf.setSecurityLevel(opts.SecLevel, opts.HashFamily)
    64  	if err != nil {
    65  		return nil, errors.Wrapf(err, "Failed initializing configuration")
    66  	}
    67  
    68  	swCSP, err := sw.NewWithParams(opts.SecLevel, opts.HashFamily, keyStore)
    69  	if err != nil {
    70  		return nil, errors.Wrapf(err, "Failed initializing fallback SW BCCSP")
    71  	}
    72  
    73  	var sessPool chan pkcs11.SessionHandle
    74  	if sessionCacheSize > 0 {
    75  		sessPool = make(chan pkcs11.SessionHandle, sessionCacheSize)
    76  	}
    77  
    78  	csp := &impl{
    79  		BCCSP:       swCSP,
    80  		conf:        conf,
    81  		sessPool:    sessPool,
    82  		sessions:    map[pkcs11.SessionHandle]struct{}{},
    83  		handleCache: map[string]pkcs11.ObjectHandle{},
    84  		softVerify:  opts.SoftVerify,
    85  		keyCache:    map[string]bccsp.Key{},
    86  		immutable:   opts.Immutable,
    87  	}
    88  
    89  	return csp.initialize(opts)
    90  }
    91  
    92  func (csp *impl) initialize(opts PKCS11Opts) (*impl, error) {
    93  	if opts.Library == "" {
    94  		return nil, fmt.Errorf("pkcs11: library path not provided")
    95  	}
    96  
    97  	ctx := pkcs11.New(opts.Library)
    98  	if ctx == nil {
    99  		return nil, fmt.Errorf("pkcs11: instantiation failed for %s", opts.Library)
   100  	}
   101  	if err := ctx.Initialize(); err != nil {
   102  		logger.Debugf("initialize failed: %v", err)
   103  	}
   104  
   105  	csp.ctx = ctx
   106  	csp.pin = opts.Pin
   107  
   108  	slots, err := ctx.GetSlotList(true)
   109  	if err != nil {
   110  		return nil, errors.Wrap(err, "pkcs11: get slot list")
   111  	}
   112  
   113  	for _, s := range slots {
   114  		info, err := ctx.GetTokenInfo(s)
   115  		if err != nil || opts.Label != info.Label {
   116  			continue
   117  		}
   118  
   119  		csp.slot = s
   120  
   121  		session, err := csp.createSession()
   122  		if err != nil {
   123  			return nil, err
   124  		}
   125  
   126  		csp.returnSession(session)
   127  		return csp, nil
   128  	}
   129  
   130  	return nil, errors.Errorf("pkcs11: could not find token with label %s", opts.Label)
   131  }
   132  
   133  // KeyGen generates a key using opts.
   134  func (csp *impl) KeyGen(opts bccsp.KeyGenOpts) (k bccsp.Key, err error) {
   135  	// Validate arguments
   136  	if opts == nil {
   137  		return nil, errors.New("Invalid Opts parameter. It must not be nil")
   138  	}
   139  
   140  	// Parse algorithm
   141  	switch opts.(type) {
   142  	case *bccsp.ECDSAKeyGenOpts:
   143  		ski, pub, err := csp.generateECKey(csp.conf.ellipticCurve, opts.Ephemeral())
   144  		if err != nil {
   145  			return nil, errors.Wrapf(err, "Failed generating ECDSA key")
   146  		}
   147  		k = &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, pub}}
   148  
   149  	case *bccsp.ECDSAP256KeyGenOpts:
   150  		ski, pub, err := csp.generateECKey(oidNamedCurveP256, opts.Ephemeral())
   151  		if err != nil {
   152  			return nil, errors.Wrapf(err, "Failed generating ECDSA P256 key")
   153  		}
   154  
   155  		k = &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, pub}}
   156  
   157  	case *bccsp.ECDSAP384KeyGenOpts:
   158  		ski, pub, err := csp.generateECKey(oidNamedCurveP384, opts.Ephemeral())
   159  		if err != nil {
   160  			return nil, errors.Wrapf(err, "Failed generating ECDSA P384 key")
   161  		}
   162  
   163  		k = &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, pub}}
   164  
   165  	default:
   166  		return csp.BCCSP.KeyGen(opts)
   167  	}
   168  
   169  	return k, nil
   170  }
   171  
   172  // KeyImport imports a key from its raw representation using opts.
   173  // The opts argument should be appropriate for the primitive used.
   174  func (csp *impl) KeyImport(raw interface{}, opts bccsp.KeyImportOpts) (k bccsp.Key, err error) {
   175  	// Validate arguments
   176  	if raw == nil {
   177  		return nil, errors.New("Invalid raw. Cannot be nil")
   178  	}
   179  
   180  	if opts == nil {
   181  		return nil, errors.New("Invalid Opts parameter. It must not be nil")
   182  	}
   183  
   184  	switch opts.(type) {
   185  
   186  	case *bccsp.X509PublicKeyImportOpts:
   187  		x509Cert, ok := raw.(*x509.Certificate)
   188  		if !ok {
   189  			return nil, errors.New("[X509PublicKeyImportOpts] Invalid raw material. Expected *x509.Certificate")
   190  		}
   191  
   192  		pk := x509Cert.PublicKey
   193  
   194  		switch pk.(type) {
   195  		case *ecdsa.PublicKey:
   196  			return csp.KeyImport(pk, &bccsp.ECDSAGoPublicKeyImportOpts{Temporary: opts.Ephemeral()})
   197  		default:
   198  			return nil, errors.New("Certificate's public key type not recognized. Supported keys: [ECDSA]")
   199  		}
   200  
   201  	default:
   202  		return csp.BCCSP.KeyImport(raw, opts)
   203  
   204  	}
   205  }
   206  
   207  func (csp *impl) cacheKey(ski []byte, key bccsp.Key) {
   208  	csp.cacheLock.Lock()
   209  	csp.keyCache[hex.EncodeToString(ski)] = key
   210  	csp.cacheLock.Unlock()
   211  }
   212  
   213  func (csp *impl) cachedKey(ski []byte) (bccsp.Key, bool) {
   214  	csp.cacheLock.RLock()
   215  	defer csp.cacheLock.RUnlock()
   216  	key, ok := csp.keyCache[hex.EncodeToString(ski)]
   217  	return key, ok
   218  }
   219  
   220  // GetKey returns the key this CSP associates to
   221  // the Subject Key Identifier ski.
   222  func (csp *impl) GetKey(ski []byte) (bccsp.Key, error) {
   223  	if key, ok := csp.cachedKey(ski); ok {
   224  		return key, nil
   225  	}
   226  
   227  	pubKey, isPriv, err := csp.getECKey(ski)
   228  	if err != nil {
   229  		logger.Debugf("Key not found using PKCS11: %v", err)
   230  		return csp.BCCSP.GetKey(ski)
   231  	}
   232  
   233  	var key bccsp.Key = &ecdsaPublicKey{ski, pubKey}
   234  	if isPriv {
   235  		key = &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, pubKey}}
   236  	}
   237  
   238  	csp.cacheKey(ski, key)
   239  	return key, nil
   240  }
   241  
   242  // Sign signs digest using key k.
   243  // The opts argument should be appropriate for the primitive used.
   244  //
   245  // Note that when a signature of a hash of a larger message is needed,
   246  // the caller is responsible for hashing the larger message and passing
   247  // the hash (as digest).
   248  func (csp *impl) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) ([]byte, error) {
   249  	// Validate arguments
   250  	if k == nil {
   251  		return nil, errors.New("Invalid Key. It must not be nil")
   252  	}
   253  	if len(digest) == 0 {
   254  		return nil, errors.New("Invalid digest. Cannot be empty")
   255  	}
   256  
   257  	// Check key type
   258  	switch key := k.(type) {
   259  	case *ecdsaPrivateKey:
   260  		return csp.signECDSA(*key, digest, opts)
   261  	default:
   262  		return csp.BCCSP.Sign(key, digest, opts)
   263  	}
   264  }
   265  
   266  // Verify verifies signature against key k and digest
   267  func (csp *impl) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (bool, error) {
   268  	// Validate arguments
   269  	if k == nil {
   270  		return false, errors.New("Invalid Key. It must not be nil")
   271  	}
   272  	if len(signature) == 0 {
   273  		return false, errors.New("Invalid signature. Cannot be empty")
   274  	}
   275  	if len(digest) == 0 {
   276  		return false, errors.New("Invalid digest. Cannot be empty")
   277  	}
   278  
   279  	// Check key type
   280  	switch key := k.(type) {
   281  	case *ecdsaPrivateKey:
   282  		return csp.verifyECDSA(key.pub, signature, digest, opts)
   283  	case *ecdsaPublicKey:
   284  		return csp.verifyECDSA(*key, signature, digest, opts)
   285  	default:
   286  		return csp.BCCSP.Verify(k, signature, digest, opts)
   287  	}
   288  }
   289  
   290  // Encrypt encrypts plaintext using key k.
   291  // The opts argument should be appropriate for the primitive used.
   292  func (csp *impl) Encrypt(k bccsp.Key, plaintext []byte, opts bccsp.EncrypterOpts) ([]byte, error) {
   293  	// TODO: Add PKCS11 support for encryption, when fabric starts requiring it
   294  	return csp.BCCSP.Encrypt(k, plaintext, opts)
   295  }
   296  
   297  // Decrypt decrypts ciphertext using key k.
   298  // The opts argument should be appropriate for the primitive used.
   299  func (csp *impl) Decrypt(k bccsp.Key, ciphertext []byte, opts bccsp.DecrypterOpts) ([]byte, error) {
   300  	return csp.BCCSP.Decrypt(k, ciphertext, opts)
   301  }
   302  
   303  func (csp *impl) getSession() (session pkcs11.SessionHandle, err error) {
   304  	for {
   305  		select {
   306  		case session = <-csp.sessPool:
   307  			return
   308  		default:
   309  			// cache is empty (or completely in use), create a new session
   310  			return csp.createSession()
   311  		}
   312  	}
   313  }
   314  
   315  func (csp *impl) createSession() (pkcs11.SessionHandle, error) {
   316  	var sess pkcs11.SessionHandle
   317  	var err error
   318  
   319  	// attempt to open a session with a 100ms delay after each attempt
   320  	for i := 0; i < createSessionRetries; i++ {
   321  		sess, err = csp.ctx.OpenSession(csp.slot, pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION)
   322  		if err == nil {
   323  			logger.Debugf("Created new pkcs11 session %d on slot %d\n", sess, csp.slot)
   324  			break
   325  		}
   326  
   327  		logger.Warningf("OpenSession failed, retrying [%s]\n", err)
   328  		time.Sleep(100 * time.Millisecond)
   329  	}
   330  	if err != nil {
   331  		return 0, errors.Wrap(err, "OpenSession failed")
   332  	}
   333  
   334  	err = csp.ctx.Login(sess, pkcs11.CKU_USER, csp.pin)
   335  	if err != nil && err != pkcs11.Error(pkcs11.CKR_USER_ALREADY_LOGGED_IN) {
   336  		csp.ctx.CloseSession(sess)
   337  		return 0, errors.Wrap(err, "Login failed")
   338  	}
   339  
   340  	csp.sessLock.Lock()
   341  	csp.sessions[sess] = struct{}{}
   342  	csp.sessLock.Unlock()
   343  
   344  	return sess, nil
   345  }
   346  
   347  func (csp *impl) closeSession(session pkcs11.SessionHandle) {
   348  	if err := csp.ctx.CloseSession(session); err != nil {
   349  		logger.Debug("CloseSession failed", err)
   350  	}
   351  
   352  	csp.sessLock.Lock()
   353  	defer csp.sessLock.Unlock()
   354  
   355  	// purge the handle cache if the last session closes
   356  	delete(csp.sessions, session)
   357  	if len(csp.sessions) == 0 {
   358  		csp.clearCaches()
   359  	}
   360  }
   361  
   362  func (csp *impl) returnSession(session pkcs11.SessionHandle) {
   363  	select {
   364  	case csp.sessPool <- session:
   365  		// returned session back to session cache
   366  	default:
   367  		// have plenty of sessions in cache, dropping
   368  		csp.closeSession(session)
   369  	}
   370  }
   371  
   372  // Look for an EC key by SKI, stored in CKA_ID
   373  func (csp *impl) getECKey(ski []byte) (pubKey *ecdsa.PublicKey, isPriv bool, err error) {
   374  	session, err := csp.getSession()
   375  	if err != nil {
   376  		return nil, false, err
   377  	}
   378  	defer func() { csp.handleSessionReturn(err, session) }()
   379  
   380  	isPriv = true
   381  	_, err = csp.findKeyPairFromSKI(session, ski, privateKeyType)
   382  	if err != nil {
   383  		isPriv = false
   384  		logger.Debugf("Private key not found [%s] for SKI [%s], looking for Public key", err, hex.EncodeToString(ski))
   385  	}
   386  
   387  	publicKey, err := csp.findKeyPairFromSKI(session, ski, publicKeyType)
   388  	if err != nil {
   389  		return nil, false, fmt.Errorf("Public key not found [%s] for SKI [%s]", err, hex.EncodeToString(ski))
   390  	}
   391  
   392  	ecpt, marshaledOid, err := csp.ecPoint(session, publicKey)
   393  	if err != nil {
   394  		return nil, false, fmt.Errorf("Public key not found [%s] for SKI [%s]", err, hex.EncodeToString(ski))
   395  	}
   396  
   397  	curveOid := new(asn1.ObjectIdentifier)
   398  	_, err = asn1.Unmarshal(marshaledOid, curveOid)
   399  	if err != nil {
   400  		return nil, false, fmt.Errorf("Failed Unmarshaling Curve OID [%s]\n%s", err.Error(), hex.EncodeToString(marshaledOid))
   401  	}
   402  
   403  	curve := namedCurveFromOID(*curveOid)
   404  	if curve == nil {
   405  		return nil, false, fmt.Errorf("Cound not recognize Curve from OID")
   406  	}
   407  	x, y := elliptic.Unmarshal(curve, ecpt)
   408  	if x == nil {
   409  		return nil, false, fmt.Errorf("Failed Unmarshaling Public Key")
   410  	}
   411  
   412  	pubKey = &ecdsa.PublicKey{Curve: curve, X: x, Y: y}
   413  	return pubKey, isPriv, nil
   414  }
   415  
   416  // RFC 5480, 2.1.1.1. Named Curve
   417  //
   418  // secp224r1 OBJECT IDENTIFIER ::= {
   419  //   iso(1) identified-organization(3) certicom(132) curve(0) 33 }
   420  //
   421  // secp256r1 OBJECT IDENTIFIER ::= {
   422  //   iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3)
   423  //   prime(1) 7 }
   424  //
   425  // secp384r1 OBJECT IDENTIFIER ::= {
   426  //   iso(1) identified-organization(3) certicom(132) curve(0) 34 }
   427  //
   428  // secp521r1 OBJECT IDENTIFIER ::= {
   429  //   iso(1) identified-organization(3) certicom(132) curve(0) 35 }
   430  //
   431  var (
   432  	oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
   433  	oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
   434  	oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
   435  	oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
   436  )
   437  
   438  func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve {
   439  	switch {
   440  	case oid.Equal(oidNamedCurveP224):
   441  		return elliptic.P224()
   442  	case oid.Equal(oidNamedCurveP256):
   443  		return elliptic.P256()
   444  	case oid.Equal(oidNamedCurveP384):
   445  		return elliptic.P384()
   446  	case oid.Equal(oidNamedCurveP521):
   447  		return elliptic.P521()
   448  	}
   449  	return nil
   450  }
   451  
   452  func (csp *impl) generateECKey(curve asn1.ObjectIdentifier, ephemeral bool) (ski []byte, pubKey *ecdsa.PublicKey, err error) {
   453  	session, err := csp.getSession()
   454  	if err != nil {
   455  		return nil, nil, err
   456  	}
   457  	defer func() { csp.handleSessionReturn(err, session) }()
   458  
   459  	id := nextIDCtr()
   460  	publabel := fmt.Sprintf("BCPUB%s", id.Text(16))
   461  	prvlabel := fmt.Sprintf("BCPRV%s", id.Text(16))
   462  
   463  	marshaledOID, err := asn1.Marshal(curve)
   464  	if err != nil {
   465  		return nil, nil, fmt.Errorf("Could not marshal OID [%s]", err.Error())
   466  	}
   467  
   468  	pubkeyT := []*pkcs11.Attribute{
   469  		pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC),
   470  		pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY),
   471  		pkcs11.NewAttribute(pkcs11.CKA_TOKEN, !ephemeral),
   472  		pkcs11.NewAttribute(pkcs11.CKA_VERIFY, true),
   473  		pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, marshaledOID),
   474  
   475  		pkcs11.NewAttribute(pkcs11.CKA_ID, publabel),
   476  		pkcs11.NewAttribute(pkcs11.CKA_LABEL, publabel),
   477  	}
   478  
   479  	prvkeyT := []*pkcs11.Attribute{
   480  		pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC),
   481  		pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY),
   482  		pkcs11.NewAttribute(pkcs11.CKA_TOKEN, !ephemeral),
   483  		pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, true),
   484  		pkcs11.NewAttribute(pkcs11.CKA_SIGN, true),
   485  
   486  		pkcs11.NewAttribute(pkcs11.CKA_ID, prvlabel),
   487  		pkcs11.NewAttribute(pkcs11.CKA_LABEL, prvlabel),
   488  
   489  		pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, false),
   490  		pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true),
   491  	}
   492  
   493  	pub, prv, err := csp.ctx.GenerateKeyPair(session,
   494  		[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_EC_KEY_PAIR_GEN, nil)},
   495  		pubkeyT,
   496  		prvkeyT,
   497  	)
   498  	if err != nil {
   499  		return nil, nil, fmt.Errorf("P11: keypair generate failed [%s]", err)
   500  	}
   501  
   502  	ecpt, _, err := csp.ecPoint(session, pub)
   503  	if err != nil {
   504  		return nil, nil, fmt.Errorf("Error querying EC-point: [%s]", err)
   505  	}
   506  	hash := sha256.Sum256(ecpt)
   507  	ski = hash[:]
   508  
   509  	// set CKA_ID of the both keys to SKI(public key) and CKA_LABEL to hex string of SKI
   510  	setskiT := []*pkcs11.Attribute{
   511  		pkcs11.NewAttribute(pkcs11.CKA_ID, ski),
   512  		pkcs11.NewAttribute(pkcs11.CKA_LABEL, hex.EncodeToString(ski)),
   513  	}
   514  
   515  	logger.Infof("Generated new P11 key, SKI %x\n", ski)
   516  	err = csp.ctx.SetAttributeValue(session, pub, setskiT)
   517  	if err != nil {
   518  		return nil, nil, fmt.Errorf("P11: set-ID-to-SKI[public] failed [%s]", err)
   519  	}
   520  
   521  	err = csp.ctx.SetAttributeValue(session, prv, setskiT)
   522  	if err != nil {
   523  		return nil, nil, fmt.Errorf("P11: set-ID-to-SKI[private] failed [%s]", err)
   524  	}
   525  
   526  	//Set CKA_Modifible to false for both public key and private keys
   527  	if csp.immutable {
   528  		setCKAModifiable := []*pkcs11.Attribute{
   529  			pkcs11.NewAttribute(pkcs11.CKA_MODIFIABLE, false),
   530  		}
   531  
   532  		_, pubCopyerror := csp.ctx.CopyObject(session, pub, setCKAModifiable)
   533  		if pubCopyerror != nil {
   534  			return nil, nil, fmt.Errorf("P11: Public Key copy failed with error [%s] . Please contact your HSM vendor", pubCopyerror)
   535  		}
   536  
   537  		pubKeyDestroyError := csp.ctx.DestroyObject(session, pub)
   538  		if pubKeyDestroyError != nil {
   539  			return nil, nil, fmt.Errorf("P11: Public Key destroy failed with error [%s]. Please contact your HSM vendor", pubCopyerror)
   540  		}
   541  
   542  		_, prvCopyerror := csp.ctx.CopyObject(session, prv, setCKAModifiable)
   543  		if prvCopyerror != nil {
   544  			return nil, nil, fmt.Errorf("P11: Private Key copy failed with error [%s]. Please contact your HSM vendor", prvCopyerror)
   545  		}
   546  		prvKeyDestroyError := csp.ctx.DestroyObject(session, prv)
   547  		if prvKeyDestroyError != nil {
   548  			return nil, nil, fmt.Errorf("P11: Private Key destroy failed with error [%s]. Please contact your HSM vendor", prvKeyDestroyError)
   549  		}
   550  	}
   551  
   552  	nistCurve := namedCurveFromOID(curve)
   553  	if curve == nil {
   554  		return nil, nil, fmt.Errorf("Cound not recognize Curve from OID")
   555  	}
   556  	x, y := elliptic.Unmarshal(nistCurve, ecpt)
   557  	if x == nil {
   558  		return nil, nil, fmt.Errorf("Failed Unmarshaling Public Key")
   559  	}
   560  
   561  	pubGoKey := &ecdsa.PublicKey{Curve: nistCurve, X: x, Y: y}
   562  
   563  	if logger.IsEnabledFor(zapcore.DebugLevel) {
   564  		listAttrs(csp.ctx, session, prv)
   565  		listAttrs(csp.ctx, session, pub)
   566  	}
   567  
   568  	return ski, pubGoKey, nil
   569  }
   570  
   571  func (csp *impl) signP11ECDSA(ski []byte, msg []byte) (R, S *big.Int, err error) {
   572  	session, err := csp.getSession()
   573  	if err != nil {
   574  		return nil, nil, err
   575  	}
   576  	defer func() { csp.handleSessionReturn(err, session) }()
   577  
   578  	privateKey, err := csp.findKeyPairFromSKI(session, ski, privateKeyType)
   579  	if err != nil {
   580  		return nil, nil, fmt.Errorf("Private key not found [%s]", err)
   581  	}
   582  
   583  	err = csp.ctx.SignInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_ECDSA, nil)}, privateKey)
   584  	if err != nil {
   585  		return nil, nil, fmt.Errorf("Sign-initialize  failed [%s]", err)
   586  	}
   587  
   588  	var sig []byte
   589  
   590  	sig, err = csp.ctx.Sign(session, msg)
   591  	if err != nil {
   592  		return nil, nil, fmt.Errorf("P11: sign failed [%s]", err)
   593  	}
   594  
   595  	R = new(big.Int)
   596  	S = new(big.Int)
   597  	R.SetBytes(sig[0 : len(sig)/2])
   598  	S.SetBytes(sig[len(sig)/2:])
   599  
   600  	return R, S, nil
   601  }
   602  
   603  func (csp *impl) verifyP11ECDSA(ski []byte, msg []byte, R, S *big.Int, byteSize int) (bool, error) {
   604  	session, err := csp.getSession()
   605  	if err != nil {
   606  		return false, err
   607  	}
   608  	defer func() { csp.handleSessionReturn(err, session) }()
   609  
   610  	logger.Debugf("Verify ECDSA\n")
   611  
   612  	publicKey, err := csp.findKeyPairFromSKI(session, ski, publicKeyType)
   613  	if err != nil {
   614  		return false, fmt.Errorf("Public key not found [%s]", err)
   615  	}
   616  
   617  	r := R.Bytes()
   618  	s := S.Bytes()
   619  
   620  	// Pad front of R and S with Zeroes if needed
   621  	sig := make([]byte, 2*byteSize)
   622  	copy(sig[byteSize-len(r):byteSize], r)
   623  	copy(sig[2*byteSize-len(s):], s)
   624  
   625  	err = csp.ctx.VerifyInit(
   626  		session,
   627  		[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_ECDSA, nil)},
   628  		publicKey,
   629  	)
   630  	if err != nil {
   631  		return false, fmt.Errorf("PKCS11: Verify-initialize [%s]", err)
   632  	}
   633  	err = csp.ctx.Verify(session, msg, sig)
   634  	if err == pkcs11.Error(pkcs11.CKR_SIGNATURE_INVALID) {
   635  		return false, nil
   636  	}
   637  	if err != nil {
   638  		return false, fmt.Errorf("PKCS11: Verify failed [%s]", err)
   639  	}
   640  
   641  	return true, nil
   642  }
   643  
   644  type keyType int8
   645  
   646  const (
   647  	publicKeyType keyType = iota
   648  	privateKeyType
   649  )
   650  
   651  func (csp *impl) cachedHandle(keyType keyType, ski []byte) (pkcs11.ObjectHandle, bool) {
   652  	cacheKey := hex.EncodeToString(append([]byte{byte(keyType)}, ski...))
   653  	csp.cacheLock.RLock()
   654  	defer csp.cacheLock.RUnlock()
   655  
   656  	handle, ok := csp.handleCache[cacheKey]
   657  	return handle, ok
   658  }
   659  
   660  func (csp *impl) cacheHandle(keyType keyType, ski []byte, handle pkcs11.ObjectHandle) {
   661  	cacheKey := hex.EncodeToString(append([]byte{byte(keyType)}, ski...))
   662  	csp.cacheLock.Lock()
   663  	defer csp.cacheLock.Unlock()
   664  
   665  	csp.handleCache[cacheKey] = handle
   666  }
   667  
   668  func (csp *impl) clearCaches() {
   669  	csp.cacheLock.Lock()
   670  	defer csp.cacheLock.Unlock()
   671  	csp.handleCache = map[string]pkcs11.ObjectHandle{}
   672  	csp.keyCache = map[string]bccsp.Key{}
   673  }
   674  
   675  func (csp *impl) findKeyPairFromSKI(session pkcs11.SessionHandle, ski []byte, keyType keyType) (pkcs11.ObjectHandle, error) {
   676  	// check for cached handle
   677  	if handle, ok := csp.cachedHandle(keyType, ski); ok {
   678  		return handle, nil
   679  	}
   680  
   681  	ktype := pkcs11.CKO_PUBLIC_KEY
   682  	if keyType == privateKeyType {
   683  		ktype = pkcs11.CKO_PRIVATE_KEY
   684  	}
   685  
   686  	template := []*pkcs11.Attribute{
   687  		pkcs11.NewAttribute(pkcs11.CKA_CLASS, ktype),
   688  		pkcs11.NewAttribute(pkcs11.CKA_ID, ski),
   689  	}
   690  	if err := csp.ctx.FindObjectsInit(session, template); err != nil {
   691  		return 0, err
   692  	}
   693  	defer csp.ctx.FindObjectsFinal(session)
   694  
   695  	// single session instance, assume one hit only
   696  	objs, _, err := csp.ctx.FindObjects(session, 1)
   697  	if err != nil {
   698  		return 0, err
   699  	}
   700  
   701  	if len(objs) == 0 {
   702  		return 0, fmt.Errorf("Key not found [%s]", hex.Dump(ski))
   703  	}
   704  
   705  	// cache the found handle
   706  	csp.cacheHandle(keyType, ski, objs[0])
   707  
   708  	return objs[0], nil
   709  }
   710  
   711  // Fairly straightforward EC-point query, other than opencryptoki
   712  // mis-reporting length, including the 04 Tag of the field following
   713  // the SPKI in EP11-returned MACed publickeys:
   714  //
   715  // attr type 385/x181, length 66 b  -- SHOULD be 1+64
   716  // EC point:
   717  // 00000000  04 ce 30 31 6d 5a fd d3  53 2d 54 9a 27 54 d8 7c
   718  // 00000010  d9 80 35 91 09 2d 6f 06  5a 8e e3 cb c0 01 b7 c9
   719  // 00000020  13 5d 70 d4 e5 62 f2 1b  10 93 f7 d5 77 41 ba 9d
   720  // 00000030  93 3e 18 3e 00 c6 0a 0e  d2 36 cc 7f be 50 16 ef
   721  // 00000040  06 04
   722  //
   723  // cf. correct field:
   724  //   0  89: SEQUENCE {
   725  //   2  19:   SEQUENCE {
   726  //   4   7:     OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
   727  //  13   8:     OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7)
   728  //        :     }
   729  //  23  66:   BIT STRING
   730  //        :     04 CE 30 31 6D 5A FD D3 53 2D 54 9A 27 54 D8 7C
   731  //        :     D9 80 35 91 09 2D 6F 06 5A 8E E3 CB C0 01 B7 C9
   732  //        :     13 5D 70 D4 E5 62 F2 1B 10 93 F7 D5 77 41 BA 9D
   733  //        :     93 3E 18 3E 00 C6 0A 0E D2 36 CC 7F BE 50 16 EF
   734  //        :     06
   735  //        :   }
   736  //
   737  // as a short-term workaround, remove the trailing byte if:
   738  //   - receiving an even number of bytes == 2*prime-coordinate +2 bytes
   739  //   - starting byte is 04: uncompressed EC point
   740  //   - trailing byte is 04: assume it belongs to the next OCTET STRING
   741  //
   742  // [mis-parsing encountered with v3.5.1, 2016-10-22]
   743  //
   744  // SoftHSM reports extra two bytes before the uncompressed point
   745  // 0x04 || <Length*2+1>
   746  //                 VV< Actual start of point
   747  // 00000000  04 41 04 6c c8 57 32 13  02 12 6a 19 23 1d 5a 64  |.A.l.W2...j.#.Zd|
   748  // 00000010  33 0c eb 75 4d e8 99 22  92 35 96 b2 39 58 14 1e  |3..uM..".5..9X..|
   749  // 00000020  19 de ef 32 46 50 68 02  24 62 36 db ed b1 84 7b  |...2FPh.$b6....{|
   750  // 00000030  93 d8 40 c3 d5 a6 b7 38  16 d2 35 0a 53 11 f9 51  |..@....8..5.S..Q|
   751  // 00000040  fc a7 16                                          |...|
   752  func (csp *impl) ecPoint(session pkcs11.SessionHandle, key pkcs11.ObjectHandle) (ecpt, oid []byte, err error) {
   753  	template := []*pkcs11.Attribute{
   754  		pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, nil),
   755  		pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, nil),
   756  	}
   757  
   758  	attr, err := csp.ctx.GetAttributeValue(session, key, template)
   759  	if err != nil {
   760  		return nil, nil, fmt.Errorf("PKCS11: get(EC point) [%s]", err)
   761  	}
   762  
   763  	for _, a := range attr {
   764  		if a.Type == pkcs11.CKA_EC_POINT {
   765  			logger.Debugf("EC point: attr type %d/0x%x, len %d\n%s\n", a.Type, a.Type, len(a.Value), hex.Dump(a.Value))
   766  
   767  			// workarounds, see above
   768  			if ((len(a.Value) % 2) == 0) &&
   769  				(byte(0x04) == a.Value[0]) &&
   770  				(byte(0x04) == a.Value[len(a.Value)-1]) {
   771  				logger.Debugf("Detected opencryptoki bug, trimming trailing 0x04")
   772  				ecpt = a.Value[0 : len(a.Value)-1] // Trim trailing 0x04
   773  			} else if byte(0x04) == a.Value[0] && byte(0x04) == a.Value[2] {
   774  				logger.Debugf("Detected SoftHSM bug, trimming leading 0x04 0xXX")
   775  				ecpt = a.Value[2:len(a.Value)]
   776  			} else {
   777  				ecpt = a.Value
   778  			}
   779  		} else if a.Type == pkcs11.CKA_EC_PARAMS {
   780  			logger.Debugf("EC point: attr type %d/0x%x, len %d\n%s\n", a.Type, a.Type, len(a.Value), hex.Dump(a.Value))
   781  
   782  			oid = a.Value
   783  		}
   784  	}
   785  	if oid == nil || ecpt == nil {
   786  		return nil, nil, fmt.Errorf("CKA_EC_POINT not found, perhaps not an EC Key?")
   787  	}
   788  
   789  	return ecpt, oid, nil
   790  }
   791  
   792  func (csp *impl) handleSessionReturn(err error, session pkcs11.SessionHandle) {
   793  	if err != nil {
   794  		if regex.MatchString(err.Error()) {
   795  			logger.Infof("PKCS11 session invalidated, closing session: %v", err)
   796  			csp.closeSession(session)
   797  			return
   798  		}
   799  	}
   800  	csp.returnSession(session)
   801  }
   802  
   803  func listAttrs(p11lib *pkcs11.Ctx, session pkcs11.SessionHandle, obj pkcs11.ObjectHandle) {
   804  	var cktype, ckclass uint
   805  	var ckaid, cklabel []byte
   806  
   807  	if p11lib == nil {
   808  		return
   809  	}
   810  
   811  	template := []*pkcs11.Attribute{
   812  		pkcs11.NewAttribute(pkcs11.CKA_CLASS, ckclass),
   813  		pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, cktype),
   814  		pkcs11.NewAttribute(pkcs11.CKA_ID, ckaid),
   815  		pkcs11.NewAttribute(pkcs11.CKA_LABEL, cklabel),
   816  	}
   817  
   818  	// certain errors are tolerated, if value is missing
   819  	attr, err := p11lib.GetAttributeValue(session, obj, template)
   820  	if err != nil {
   821  		logger.Debugf("P11: get(attrlist) [%s]\n", err)
   822  	}
   823  
   824  	for _, a := range attr {
   825  		// Would be friendlier if the bindings provided a way convert Attribute hex to string
   826  		logger.Debugf("ListAttr: type %d/0x%x, length %d\n%s", a.Type, a.Type, len(a.Value), hex.Dump(a.Value))
   827  	}
   828  }
   829  
   830  var (
   831  	bigone  = new(big.Int).SetInt64(1)
   832  	idCtr   = new(big.Int)
   833  	idMutex sync.Mutex
   834  )
   835  
   836  func nextIDCtr() *big.Int {
   837  	idMutex.Lock()
   838  	idCtr = new(big.Int).Add(idCtr, bigone)
   839  	idMutex.Unlock()
   840  	return idCtr
   841  }
   842  
   843  // FindPKCS11Lib IS ONLY USED FOR TESTING
   844  // This is a convenience function. Useful to self-configure, for tests where
   845  // usual configuration is not available.
   846  func FindPKCS11Lib() (lib, pin, label string) {
   847  	if lib = os.Getenv("PKCS11_LIB"); lib == "" {
   848  		possibilities := []string{
   849  			"/usr/lib/softhsm/libsofthsm2.so",                  //Debian
   850  			"/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so", //Ubuntu
   851  		}
   852  		for _, path := range possibilities {
   853  			if _, err := os.Stat(path); !os.IsNotExist(err) {
   854  				lib = path
   855  				break
   856  			}
   857  		}
   858  	}
   859  	if pin = os.Getenv("PKCS11_PIN"); pin == "" {
   860  		pin = "98765432"
   861  	}
   862  	if label = os.Getenv("PKCS11_LABEL"); label == "" {
   863  		label = "ForFabric"
   864  	}
   865  
   866  	return lib, pin, label
   867  }