github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/bccsp/pkcs11/pkcs11.go (about)

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