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