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