github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/bccsp/pkcs11/pkcs11.go (about)

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