github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric/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/elliptic"
    11  	"crypto/sha256"
    12  	"encoding/asn1"
    13  	"encoding/hex"
    14  	"fmt"
    15  	"github.com/hellobchain/newcryptosm/ecdsa"
    16  	"math/big"
    17  	"sync"
    18  
    19  	"github.com/miekg/pkcs11"
    20  	"go.uber.org/zap/zapcore"
    21  )
    22  
    23  func loadLib(lib, pin, label string) (*pkcs11.Ctx, uint, *pkcs11.SessionHandle, error) {
    24  	var slot uint
    25  	logger.Debugf("Loading pkcs11 library [%s]\n", lib)
    26  	if lib == "" {
    27  		return nil, slot, nil, fmt.Errorf("No PKCS11 library default")
    28  	}
    29  
    30  	ctx := pkcs11.New(lib)
    31  	if ctx == nil {
    32  		return nil, slot, nil, fmt.Errorf("Instantiate failed [%s]", lib)
    33  	}
    34  
    35  	ctx.Initialize()
    36  	slots, err := ctx.GetSlotList(true)
    37  	if err != nil {
    38  		return nil, slot, nil, fmt.Errorf("Could not get Slot List [%s]", err)
    39  	}
    40  	found := false
    41  	for _, s := range slots {
    42  		info, errToken := ctx.GetTokenInfo(s)
    43  		if errToken != nil {
    44  			continue
    45  		}
    46  		logger.Debugf("Looking for %s, found label %s\n", label, info.Label)
    47  		if label == info.Label {
    48  			found = true
    49  			slot = s
    50  			break
    51  		}
    52  	}
    53  	if !found {
    54  		return nil, slot, nil, fmt.Errorf("Could not find token with label %s", label)
    55  	}
    56  
    57  	session := createSession(ctx, slot, pin)
    58  
    59  	logger.Debugf("Created new pkcs11 session %+v on slot %d\n", session, slot)
    60  
    61  	if pin == "" {
    62  		return nil, slot, nil, fmt.Errorf("No PIN set")
    63  	}
    64  	err = ctx.Login(session, pkcs11.CKU_USER, pin)
    65  	if err != nil {
    66  		if err != pkcs11.Error(pkcs11.CKR_USER_ALREADY_LOGGED_IN) {
    67  			return nil, slot, nil, fmt.Errorf("Login failed [%s]", err)
    68  		}
    69  	}
    70  
    71  	return ctx, slot, &session, nil
    72  }
    73  
    74  func (csp *impl) getSession() (session pkcs11.SessionHandle) {
    75  	select {
    76  	case session = <-csp.sessions:
    77  		_, err := csp.ctx.GetSessionInfo(session)
    78  		if err != nil {
    79  			logger.Warningf("Get session info failed [%s], closing existing session and getting a new session\n", err)
    80  			csp.ctx.CloseSession(session)
    81  			session = createSession(csp.ctx, csp.slot, csp.pin)
    82  		} else {
    83  			logger.Debugf("Reusing existing pkcs11 session %+v on slot %d\n", session, csp.slot)
    84  		}
    85  
    86  	default:
    87  		// cache is empty (or completely in use), create a new session
    88  		session = createSession(csp.ctx, csp.slot, csp.pin)
    89  	}
    90  	return session
    91  }
    92  
    93  func createSession(ctx *pkcs11.Ctx, slot uint, pin string) pkcs11.SessionHandle {
    94  	var s pkcs11.SessionHandle
    95  	var err error
    96  	for i := 0; i < 10; i++ {
    97  		s, err = ctx.OpenSession(slot, pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION)
    98  		if err != nil {
    99  			logger.Warningf("OpenSession failed, retrying [%s]\n", err)
   100  		} else {
   101  			break
   102  		}
   103  	}
   104  	if err != nil {
   105  		logger.Fatalf("OpenSession failed [%s]", err)
   106  	}
   107  	logger.Debugf("Created new pkcs11 session %+v on slot %d\n", s, slot)
   108  	session := s
   109  
   110  	err = ctx.Login(session, pkcs11.CKU_USER, pin)
   111  	if err != nil {
   112  		if err != pkcs11.Error(pkcs11.CKR_USER_ALREADY_LOGGED_IN) {
   113  			logger.Errorf("Login failed [%s]", err)
   114  		}
   115  	}
   116  	return session
   117  }
   118  
   119  func (csp *impl) returnSession(session pkcs11.SessionHandle) {
   120  	select {
   121  	case csp.sessions <- session:
   122  		// returned session back to session cache
   123  	default:
   124  		// have plenty of sessions in cache, dropping
   125  		csp.ctx.CloseSession(session)
   126  	}
   127  }
   128  
   129  // Look for an EC key by SKI, stored in CKA_ID
   130  // This function can probably be adapted for both EC and RSA keys.
   131  func (csp *impl) getECKey(ski []byte) (pubKey *ecdsa.PublicKey, isPriv bool, err error) {
   132  	p11lib := csp.ctx
   133  	session := csp.getSession()
   134  	defer csp.returnSession(session)
   135  	isPriv = true
   136  	_, err = findKeyPairFromSKI(p11lib, session, ski, csp.altId, privateKeyFlag)
   137  	if err != nil {
   138  		isPriv = false
   139  		logger.Debugf("Private key not found [%s] for SKI [%s], looking for Public key", err, hex.EncodeToString(ski))
   140  	}
   141  
   142  	publicKey, err := findKeyPairFromSKI(p11lib, session, ski, csp.altId, publicKeyFlag)
   143  	if err != nil {
   144  		return nil, false, fmt.Errorf("Public key not found [%s] for SKI [%s]", err, hex.EncodeToString(ski))
   145  	}
   146  
   147  	ecpt, marshaledOid, err := ecPoint(p11lib, session, *publicKey)
   148  	if err != nil {
   149  		return nil, false, fmt.Errorf("Public key not found [%s] for SKI [%s]", err, hex.EncodeToString(ski))
   150  	}
   151  
   152  	curveOid := new(asn1.ObjectIdentifier)
   153  	_, err = asn1.Unmarshal(marshaledOid, curveOid)
   154  	if err != nil {
   155  		return nil, false, fmt.Errorf("Failed Unmarshaling Curve OID [%s]\n%s", err.Error(), hex.EncodeToString(marshaledOid))
   156  	}
   157  
   158  	curve := namedCurveFromOID(*curveOid)
   159  	if curve == nil {
   160  		return nil, false, fmt.Errorf("Cound not recognize Curve from OID")
   161  	}
   162  	x, y := elliptic.Unmarshal(curve, ecpt)
   163  	if x == nil {
   164  		return nil, false, fmt.Errorf("Failed Unmarshaling Public Key")
   165  	}
   166  
   167  	pubKey = &ecdsa.PublicKey{Curve: curve, X: x, Y: y}
   168  	return pubKey, isPriv, nil
   169  }
   170  
   171  // RFC 5480, 2.1.1.1. Named Curve
   172  //
   173  // secp224r1 OBJECT IDENTIFIER ::= {
   174  //   iso(1) identified-organization(3) certicom(132) curve(0) 33 }
   175  //
   176  // secp256r1 OBJECT IDENTIFIER ::= {
   177  //   iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3)
   178  //   prime(1) 7 }
   179  //
   180  // secp384r1 OBJECT IDENTIFIER ::= {
   181  //   iso(1) identified-organization(3) certicom(132) curve(0) 34 }
   182  //
   183  // secp521r1 OBJECT IDENTIFIER ::= {
   184  //   iso(1) identified-organization(3) certicom(132) curve(0) 35 }
   185  //
   186  var (
   187  	oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
   188  	oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
   189  	oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
   190  	oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
   191  )
   192  
   193  func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve {
   194  	switch {
   195  	case oid.Equal(oidNamedCurveP224):
   196  		return elliptic.P224()
   197  	case oid.Equal(oidNamedCurveP256):
   198  		return elliptic.P256()
   199  	case oid.Equal(oidNamedCurveP384):
   200  		return elliptic.P384()
   201  	case oid.Equal(oidNamedCurveP521):
   202  		return elliptic.P521()
   203  	}
   204  	return nil
   205  }
   206  
   207  func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) {
   208  	switch curve {
   209  	case elliptic.P224():
   210  		return oidNamedCurveP224, true
   211  	case elliptic.P256():
   212  		return oidNamedCurveP256, true
   213  	case elliptic.P384():
   214  		return oidNamedCurveP384, true
   215  	case elliptic.P521():
   216  		return oidNamedCurveP521, true
   217  	}
   218  
   219  	return nil, false
   220  }
   221  
   222  func (csp *impl) generateECKey(curve asn1.ObjectIdentifier, ephemeral bool) (ski []byte, pubKey *ecdsa.PublicKey, err error) {
   223  	p11lib := csp.ctx
   224  	session := csp.getSession()
   225  	defer csp.returnSession(session)
   226  
   227  	keylabel := ""
   228  	updateSKI := false
   229  	if csp.altId == "" {
   230  		// Generate using the SKI process and then make keypair immutable according to csp.immutable
   231  		keylabel = fmt.Sprintf("BCP%s", nextIDCtr().Text(16))
   232  		updateSKI = true
   233  	} else if csp.altId != "" && csp.immutable {
   234  		// Generate the key pair using AltID process.
   235  		// No need to worry about immutable since AltID is used with Write-Once HSMs
   236  		keylabel = csp.altId
   237  		updateSKI = false
   238  	} else if csp.altId != "" && !csp.immutable {
   239  		// Raise an error since AltID is used with Write-Once HSMs
   240  		// So cannot make support AltID with immutable = false.
   241  		return nil, nil, fmt.Errorf("Cannot generate a mutable key using AltID.")
   242  	}
   243  
   244  	marshaledOID, err := asn1.Marshal(curve)
   245  	if err != nil {
   246  		return nil, nil, fmt.Errorf("Could not marshal OID [%s]", err.Error())
   247  	}
   248  
   249  	pubkeyT := []*pkcs11.Attribute{
   250  		pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC),
   251  		pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY),
   252  		pkcs11.NewAttribute(pkcs11.CKA_TOKEN, !ephemeral),
   253  		pkcs11.NewAttribute(pkcs11.CKA_VERIFY, true),
   254  		pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, marshaledOID),
   255  
   256  		pkcs11.NewAttribute(pkcs11.CKA_ID, []byte(keylabel)),
   257  		pkcs11.NewAttribute(pkcs11.CKA_LABEL, keylabel),
   258  	}
   259  
   260  	prvkeyT := []*pkcs11.Attribute{
   261  		pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC),
   262  		pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY),
   263  		pkcs11.NewAttribute(pkcs11.CKA_TOKEN, !ephemeral),
   264  		pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, true),
   265  		pkcs11.NewAttribute(pkcs11.CKA_SIGN, true),
   266  
   267  		pkcs11.NewAttribute(pkcs11.CKA_ID, []byte(keylabel)),
   268  		pkcs11.NewAttribute(pkcs11.CKA_LABEL, keylabel),
   269  
   270  		pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, false),
   271  		pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true),
   272  	}
   273  
   274  	pub, prv, err := p11lib.GenerateKeyPair(session,
   275  		[]*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_EC_KEY_PAIR_GEN, nil)},
   276  		pubkeyT, prvkeyT)
   277  
   278  	if err != nil {
   279  		return nil, nil, fmt.Errorf("P11: keypair generate failed [%s]", err)
   280  	}
   281  
   282  	ecpt, _, err := ecPoint(p11lib, session, pub)
   283  	if err != nil {
   284  		return nil, nil, fmt.Errorf("Error querying EC-point: [%s]", err)
   285  	}
   286  	hash := sha256.Sum256(ecpt)
   287  	ski = hash[:]
   288  
   289  	if updateSKI {
   290  		// set CKA_ID of the both keys to SKI(public key) and CKA_LABEL to hex string of SKI
   291  		setskiT := []*pkcs11.Attribute{
   292  			pkcs11.NewAttribute(pkcs11.CKA_ID, ski),
   293  			pkcs11.NewAttribute(pkcs11.CKA_LABEL, hex.EncodeToString(ski)),
   294  		}
   295  
   296  		logger.Infof("Generated new P11 key, SKI %x\n", ski)
   297  		err = p11lib.SetAttributeValue(session, pub, setskiT)
   298  		if err != nil {
   299  			return nil, nil, fmt.Errorf("P11: set-ID-to-SKI[public] failed [%s]", err)
   300  		}
   301  
   302  		err = p11lib.SetAttributeValue(session, prv, setskiT)
   303  		if err != nil {
   304  			return nil, nil, fmt.Errorf("P11: set-ID-to-SKI[private] failed [%s]", err)
   305  		}
   306  
   307  		//Set CKA_Modifible to false for both public key and private keys
   308  		if csp.immutable {
   309  			setCKAModifiable := []*pkcs11.Attribute{
   310  				pkcs11.NewAttribute(pkcs11.CKA_MODIFIABLE, false),
   311  			}
   312  
   313  			_, pubCopyerror := p11lib.CopyObject(session, pub, setCKAModifiable)
   314  			if pubCopyerror != nil {
   315  				return nil, nil, fmt.Errorf("P11: Public Key copy failed with error [%s] . Please contact your HSM vendor", pubCopyerror)
   316  			}
   317  
   318  			pubKeyDestroyError := p11lib.DestroyObject(session, pub)
   319  			if pubKeyDestroyError != nil {
   320  				return nil, nil, fmt.Errorf("P11: Public Key destroy failed with error [%s]. Please contact your HSM vendor", pubCopyerror)
   321  			}
   322  
   323  			_, prvCopyerror := p11lib.CopyObject(session, prv, setCKAModifiable)
   324  			if prvCopyerror != nil {
   325  				return nil, nil, fmt.Errorf("P11: Private Key copy failed with error [%s]. Please contact your HSM vendor", prvCopyerror)
   326  			}
   327  			prvKeyDestroyError := p11lib.DestroyObject(session, prv)
   328  			if pubKeyDestroyError != nil {
   329  				return nil, nil, fmt.Errorf("P11: Private Key destroy failed with error [%s]. Please contact your HSM vendor", prvKeyDestroyError)
   330  			}
   331  		}
   332  	}
   333  
   334  	nistCurve := namedCurveFromOID(curve)
   335  	if curve == nil {
   336  		return nil, nil, fmt.Errorf("Cound not recognize Curve from OID")
   337  	}
   338  	x, y := elliptic.Unmarshal(nistCurve, ecpt)
   339  	if x == nil {
   340  		return nil, nil, fmt.Errorf("Failed Unmarshaling Public Key")
   341  	}
   342  
   343  	pubGoKey := &ecdsa.PublicKey{Curve: nistCurve, X: x, Y: y}
   344  
   345  	if logger.IsEnabledFor(zapcore.DebugLevel) {
   346  		listAttrs(p11lib, session, prv)
   347  		listAttrs(p11lib, session, pub)
   348  	}
   349  
   350  	return ski, pubGoKey, nil
   351  }
   352  
   353  func (csp *impl) signP11ECDSA(ski []byte, msg []byte) (R, S *big.Int, err error) {
   354  	p11lib := csp.ctx
   355  	session := csp.getSession()
   356  	defer csp.returnSession(session)
   357  
   358  	privateKey, err := findKeyPairFromSKI(p11lib, session, ski, csp.altId, privateKeyFlag)
   359  	if err != nil {
   360  		return nil, nil, fmt.Errorf("Private key not found [%s]", err)
   361  	}
   362  
   363  	err = p11lib.SignInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_ECDSA, nil)}, *privateKey)
   364  	if err != nil {
   365  		return nil, nil, fmt.Errorf("Sign-initialize  failed [%s]", err)
   366  	}
   367  
   368  	var sig []byte
   369  
   370  	sig, err = p11lib.Sign(session, msg)
   371  	if err != nil {
   372  		return nil, nil, fmt.Errorf("P11: sign failed [%s]", err)
   373  	}
   374  
   375  	R = new(big.Int)
   376  	S = new(big.Int)
   377  	R.SetBytes(sig[0 : len(sig)/2])
   378  	S.SetBytes(sig[len(sig)/2:])
   379  
   380  	return R, S, nil
   381  }
   382  
   383  func (csp *impl) verifyP11ECDSA(ski []byte, msg []byte, R, S *big.Int, byteSize int) (bool, error) {
   384  	p11lib := csp.ctx
   385  	session := csp.getSession()
   386  	defer csp.returnSession(session)
   387  
   388  	logger.Debugf("Verify ECDSA\n")
   389  
   390  	publicKey, err := findKeyPairFromSKI(p11lib, session, ski, csp.altId, publicKeyFlag)
   391  	if err != nil {
   392  		return false, fmt.Errorf("Public key not found [%s]", err)
   393  	}
   394  
   395  	r := R.Bytes()
   396  	s := S.Bytes()
   397  
   398  	// Pad front of R and S with Zeroes if needed
   399  	sig := make([]byte, 2*byteSize)
   400  	copy(sig[byteSize-len(r):byteSize], r)
   401  	copy(sig[2*byteSize-len(s):], s)
   402  
   403  	err = p11lib.VerifyInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_ECDSA, nil)},
   404  		*publicKey)
   405  	if err != nil {
   406  		return false, fmt.Errorf("PKCS11: Verify-initialize [%s]", err)
   407  	}
   408  	err = p11lib.Verify(session, msg, sig)
   409  	if err == pkcs11.Error(pkcs11.CKR_SIGNATURE_INVALID) {
   410  		return false, nil
   411  	}
   412  	if err != nil {
   413  		return false, fmt.Errorf("PKCS11: Verify failed [%s]", err)
   414  	}
   415  
   416  	return true, nil
   417  }
   418  
   419  const (
   420  	privateKeyFlag = true
   421  	publicKeyFlag  = false
   422  )
   423  
   424  func findKeyPairFromSKI(mod *pkcs11.Ctx, session pkcs11.SessionHandle, ski []byte, altID string, keyType bool) (*pkcs11.ObjectHandle, error) {
   425  	ktype := pkcs11.CKO_PUBLIC_KEY
   426  	if keyType == privateKeyFlag {
   427  		ktype = pkcs11.CKO_PRIVATE_KEY
   428  	}
   429  
   430  	keyId := []byte(altID)
   431  	if altID == "" {
   432  		keyId = ski
   433  	}
   434  
   435  	template := []*pkcs11.Attribute{
   436  		pkcs11.NewAttribute(pkcs11.CKA_CLASS, ktype),
   437  		pkcs11.NewAttribute(pkcs11.CKA_ID, keyId),
   438  	}
   439  
   440  	if err := mod.FindObjectsInit(session, template); err != nil {
   441  		return nil, err
   442  	}
   443  
   444  	// single session instance, assume one hit only
   445  	objs, _, err := mod.FindObjects(session, 1)
   446  	if err != nil {
   447  		return nil, err
   448  	}
   449  	if err = mod.FindObjectsFinal(session); err != nil {
   450  		return nil, err
   451  	}
   452  
   453  	if len(objs) == 0 {
   454  		return nil, fmt.Errorf("Key not found [%s]", hex.Dump(ski))
   455  	}
   456  
   457  	return &objs[0], nil
   458  }
   459  
   460  // Fairly straightforward EC-point query, other than opencryptoki
   461  // mis-reporting length, including the 04 Tag of the field following
   462  // the SPKI in EP11-returned MACed publickeys:
   463  //
   464  // attr type 385/x181, length 66 b  -- SHOULD be 1+64
   465  // EC point:
   466  // 00000000  04 ce 30 31 6d 5a fd d3  53 2d 54 9a 27 54 d8 7c
   467  // 00000010  d9 80 35 91 09 2d 6f 06  5a 8e e3 cb c0 01 b7 c9
   468  // 00000020  13 5d 70 d4 e5 62 f2 1b  10 93 f7 d5 77 41 ba 9d
   469  // 00000030  93 3e 18 3e 00 c6 0a 0e  d2 36 cc 7f be 50 16 ef
   470  // 00000040  06 04
   471  //
   472  // cf. correct field:
   473  //   0  89: SEQUENCE {
   474  //   2  19:   SEQUENCE {
   475  //   4   7:     OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
   476  //  13   8:     OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7)
   477  //        :     }
   478  //  23  66:   BIT STRING
   479  //        :     04 CE 30 31 6D 5A FD D3 53 2D 54 9A 27 54 D8 7C
   480  //        :     D9 80 35 91 09 2D 6F 06 5A 8E E3 CB C0 01 B7 C9
   481  //        :     13 5D 70 D4 E5 62 F2 1B 10 93 F7 D5 77 41 BA 9D
   482  //        :     93 3E 18 3E 00 C6 0A 0E D2 36 CC 7F BE 50 16 EF
   483  //        :     06
   484  //        :   }
   485  //
   486  // as a short-term workaround, remove the trailing byte if:
   487  //   - receiving an even number of bytes == 2*prime-coordinate +2 bytes
   488  //   - starting byte is 04: uncompressed EC point
   489  //   - trailing byte is 04: assume it belongs to the next OCTET STRING
   490  //
   491  // [mis-parsing encountered with v3.5.1, 2016-10-22]
   492  //
   493  // SoftHSM reports extra two bytes before the uncompressed point
   494  // 0x04 || <Length*2+1>
   495  //                 VV< Actual start of point
   496  // 00000000  04 41 04 6c c8 57 32 13  02 12 6a 19 23 1d 5a 64  |.A.l.W2...j.#.Zd|
   497  // 00000010  33 0c eb 75 4d e8 99 22  92 35 96 b2 39 58 14 1e  |3..uM..".5..9X..|
   498  // 00000020  19 de ef 32 46 50 68 02  24 62 36 db ed b1 84 7b  |...2FPh.$b6....{|
   499  // 00000030  93 d8 40 c3 d5 a6 b7 38  16 d2 35 0a 53 11 f9 51  |..@....8..5.S..Q|
   500  // 00000040  fc a7 16                                          |...|
   501  func ecPoint(p11lib *pkcs11.Ctx, session pkcs11.SessionHandle, key pkcs11.ObjectHandle) (ecpt, oid []byte, err error) {
   502  	template := []*pkcs11.Attribute{
   503  		pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, nil),
   504  		pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, nil),
   505  	}
   506  
   507  	attr, err := p11lib.GetAttributeValue(session, key, template)
   508  	if err != nil {
   509  		return nil, nil, fmt.Errorf("PKCS11: get(EC point) [%s]", err)
   510  	}
   511  
   512  	for _, a := range attr {
   513  		if a.Type == pkcs11.CKA_EC_POINT {
   514  			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))
   515  
   516  			// workarounds, see above
   517  			if (0 == (len(a.Value) % 2)) &&
   518  				(byte(0x04) == a.Value[0]) &&
   519  				(byte(0x04) == a.Value[len(a.Value)-1]) {
   520  				logger.Debugf("Detected opencryptoki bug, trimming trailing 0x04")
   521  				ecpt = a.Value[0 : len(a.Value)-1] // Trim trailing 0x04
   522  			} else if byte(0x04) == a.Value[0] && byte(0x04) == a.Value[2] {
   523  				logger.Debugf("Detected SoftHSM bug, trimming leading 0x04 0xXX")
   524  				ecpt = a.Value[2:len(a.Value)]
   525  			} else {
   526  				ecpt = a.Value
   527  			}
   528  		} else if a.Type == pkcs11.CKA_EC_PARAMS {
   529  			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))
   530  
   531  			oid = a.Value
   532  		}
   533  	}
   534  	if oid == nil || ecpt == nil {
   535  		return nil, nil, fmt.Errorf("CKA_EC_POINT not found, perhaps not an EC Key?")
   536  	}
   537  
   538  	return ecpt, oid, nil
   539  }
   540  
   541  func listAttrs(p11lib *pkcs11.Ctx, session pkcs11.SessionHandle, obj pkcs11.ObjectHandle) {
   542  	var cktype, ckclass uint
   543  	var ckaid, cklabel []byte
   544  
   545  	if p11lib == nil {
   546  		return
   547  	}
   548  
   549  	template := []*pkcs11.Attribute{
   550  		pkcs11.NewAttribute(pkcs11.CKA_CLASS, ckclass),
   551  		pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, cktype),
   552  		pkcs11.NewAttribute(pkcs11.CKA_ID, ckaid),
   553  		pkcs11.NewAttribute(pkcs11.CKA_LABEL, cklabel),
   554  	}
   555  
   556  	// certain errors are tolerated, if value is missing
   557  	attr, err := p11lib.GetAttributeValue(session, obj, template)
   558  	if err != nil {
   559  		logger.Debugf("P11: get(attrlist) [%s]\n", err)
   560  	}
   561  
   562  	for _, a := range attr {
   563  		// Would be friendlier if the bindings provided a way convert Attribute hex to string
   564  		logger.Debugf("ListAttr: type %d/0x%x, length %d\n%s", a.Type, a.Type, len(a.Value), hex.Dump(a.Value))
   565  	}
   566  }
   567  
   568  func (csp *impl) getSecretValue(ski []byte) []byte {
   569  	p11lib := csp.ctx
   570  	session := csp.getSession()
   571  	defer csp.returnSession(session)
   572  
   573  	keyHandle, err := findKeyPairFromSKI(p11lib, session, ski, csp.altId, privateKeyFlag)
   574  	if err != nil {
   575  		logger.Warningf("P11: findKeyPairFromSKI [%s]\n", err)
   576  	}
   577  	var privKey []byte
   578  	template := []*pkcs11.Attribute{
   579  		pkcs11.NewAttribute(pkcs11.CKA_VALUE, privKey),
   580  	}
   581  
   582  	// certain errors are tolerated, if value is missing
   583  	attr, err := p11lib.GetAttributeValue(session, *keyHandle, template)
   584  	if err != nil {
   585  		logger.Warningf("P11: get(attrlist) [%s]\n", err)
   586  	}
   587  
   588  	for _, a := range attr {
   589  		// Would be friendlier if the bindings provided a way convert Attribute hex to string
   590  		logger.Debugf("ListAttr: type %d/0x%x, length %d\n%s", a.Type, a.Type, len(a.Value), hex.Dump(a.Value))
   591  		return a.Value
   592  	}
   593  	logger.Warningf("No Key Value found: %v", err)
   594  	return nil
   595  }
   596  
   597  var (
   598  	bigone  = new(big.Int).SetInt64(1)
   599  	idCtr   = new(big.Int)
   600  	idMutex sync.Mutex
   601  )
   602  
   603  func nextIDCtr() *big.Int {
   604  	idMutex.Lock()
   605  	idCtr = new(big.Int).Add(idCtr, bigone)
   606  	idMutex.Unlock()
   607  	return idCtr
   608  }