github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/bccsp/pkcs11/impl.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 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/rsa"
    22  	"crypto/sha256"
    23  	"crypto/x509"
    24  	"errors"
    25  	"fmt"
    26  	"math/big"
    27  	"os"
    28  
    29  	"github.com/hyperledger/fabric/bccsp"
    30  	"github.com/hyperledger/fabric/bccsp/sw"
    31  	"github.com/hyperledger/fabric/bccsp/utils"
    32  	"github.com/hyperledger/fabric/common/flogging"
    33  	"github.com/miekg/pkcs11"
    34  )
    35  
    36  var (
    37  	logger           = flogging.MustGetLogger("bccsp_p11")
    38  	sessionCacheSize = 10
    39  )
    40  
    41  // New returns a new instance of the software-based BCCSP
    42  // set at the passed security level, hash family and KeyStore.
    43  func New(opts PKCS11Opts, keyStore bccsp.KeyStore) (bccsp.BCCSP, error) {
    44  	// Init config
    45  	conf := &config{}
    46  	err := conf.setSecurityLevel(opts.SecLevel, opts.HashFamily)
    47  	if err != nil {
    48  		return nil, fmt.Errorf("Failed initializing configuration [%s]", err)
    49  	}
    50  
    51  	swCSP, err := sw.New(opts.SecLevel, opts.HashFamily, keyStore)
    52  	if err != nil {
    53  		return nil, fmt.Errorf("Failed initializing fallback SW BCCSP [%s]", err)
    54  	}
    55  
    56  	// Check KeyStore
    57  	if keyStore == nil {
    58  		return nil, errors.New("Invalid bccsp.KeyStore instance. It must be different from nil.")
    59  	}
    60  
    61  	lib := opts.Library
    62  	pin := opts.Pin
    63  	label := opts.Label
    64  	ctx, slot, session, err := loadLib(lib, pin, label)
    65  	if err != nil {
    66  		return nil, fmt.Errorf("Failed initializing PKCS11 library %s %s [%s]",
    67  			lib, label, err)
    68  	}
    69  
    70  	sessions := make(chan pkcs11.SessionHandle, sessionCacheSize)
    71  	csp := &impl{swCSP, conf, keyStore, ctx, sessions, slot, lib, opts.Sensitive, opts.SoftVerify}
    72  	csp.returnSession(*session)
    73  	return csp, nil
    74  }
    75  
    76  type impl struct {
    77  	bccsp.BCCSP
    78  
    79  	conf *config
    80  	ks   bccsp.KeyStore
    81  
    82  	ctx      *pkcs11.Ctx
    83  	sessions chan pkcs11.SessionHandle
    84  	slot     uint
    85  
    86  	lib          string
    87  	noPrivImport bool
    88  	softVerify   bool
    89  }
    90  
    91  // KeyGen generates a key using opts.
    92  func (csp *impl) KeyGen(opts bccsp.KeyGenOpts) (k bccsp.Key, err error) {
    93  	// Validate arguments
    94  	if opts == nil {
    95  		return nil, errors.New("Invalid Opts parameter. It must not be nil.")
    96  	}
    97  
    98  	// Parse algorithm
    99  	switch opts.(type) {
   100  	case *bccsp.ECDSAKeyGenOpts:
   101  		ski, pub, err := csp.generateECKey(csp.conf.ellipticCurve, opts.Ephemeral())
   102  		if err != nil {
   103  			return nil, fmt.Errorf("Failed generating ECDSA key [%s]", err)
   104  		}
   105  		k = &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, pub}}
   106  
   107  	case *bccsp.ECDSAP256KeyGenOpts:
   108  		ski, pub, err := csp.generateECKey(oidNamedCurveP256, opts.Ephemeral())
   109  		if err != nil {
   110  			return nil, fmt.Errorf("Failed generating ECDSA P256 key [%s]", err)
   111  		}
   112  
   113  		k = &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, pub}}
   114  
   115  	case *bccsp.ECDSAP384KeyGenOpts:
   116  		ski, pub, err := csp.generateECKey(oidNamedCurveP384, opts.Ephemeral())
   117  		if err != nil {
   118  			return nil, fmt.Errorf("Failed generating ECDSA P384 key [%s]", err)
   119  		}
   120  
   121  		k = &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, pub}}
   122  
   123  	default:
   124  		return csp.BCCSP.KeyGen(opts)
   125  	}
   126  
   127  	return k, nil
   128  }
   129  
   130  // KeyDeriv derives a key from k using opts.
   131  // The opts argument should be appropriate for the primitive used.
   132  func (csp *impl) KeyDeriv(k bccsp.Key, opts bccsp.KeyDerivOpts) (dk bccsp.Key, err error) {
   133  	// Validate arguments
   134  	if k == nil {
   135  		return nil, errors.New("Invalid Key. It must not be nil.")
   136  	}
   137  
   138  	// Derive key
   139  	switch k.(type) {
   140  	case *ecdsaPublicKey:
   141  		// Validate opts
   142  		if opts == nil {
   143  			return nil, errors.New("Invalid Opts parameter. It must not be nil.")
   144  		}
   145  
   146  		ecdsaK := k.(*ecdsaPublicKey)
   147  
   148  		switch opts.(type) {
   149  
   150  		// Re-randomized an ECDSA public key
   151  		case *bccsp.ECDSAReRandKeyOpts:
   152  			pubKey := ecdsaK.pub
   153  			if pubKey == nil {
   154  				return nil, errors.New("Public base key cannot be nil.")
   155  			}
   156  			reRandOpts := opts.(*bccsp.ECDSAReRandKeyOpts)
   157  			tempSK := &ecdsa.PublicKey{
   158  				Curve: pubKey.Curve,
   159  				X:     new(big.Int),
   160  				Y:     new(big.Int),
   161  			}
   162  
   163  			var k = new(big.Int).SetBytes(reRandOpts.ExpansionValue())
   164  			var one = new(big.Int).SetInt64(1)
   165  			n := new(big.Int).Sub(pubKey.Params().N, one)
   166  			k.Mod(k, n)
   167  			k.Add(k, one)
   168  
   169  			// Compute temporary public key
   170  			tempX, tempY := pubKey.ScalarBaseMult(k.Bytes())
   171  			tempSK.X, tempSK.Y = tempSK.Add(
   172  				pubKey.X, pubKey.Y,
   173  				tempX, tempY,
   174  			)
   175  
   176  			// Verify temporary public key is a valid point on the reference curve
   177  			isOn := tempSK.Curve.IsOnCurve(tempSK.X, tempSK.Y)
   178  			if !isOn {
   179  				return nil, errors.New("Failed temporary public key IsOnCurve check.")
   180  			}
   181  
   182  			ecPt := elliptic.Marshal(tempSK.Curve, tempSK.X, tempSK.Y)
   183  			oid, ok := oidFromNamedCurve(tempSK.Curve)
   184  			if !ok {
   185  				return nil, errors.New("Do not know OID for this Curve.")
   186  			}
   187  
   188  			ski, err := csp.importECKey(oid, nil, ecPt, opts.Ephemeral(), publicKeyFlag)
   189  			if err != nil {
   190  				return nil, fmt.Errorf("Failed getting importing EC Public Key [%s]", err)
   191  			}
   192  			reRandomizedKey := &ecdsaPublicKey{ski, tempSK}
   193  
   194  			return reRandomizedKey, nil
   195  
   196  		default:
   197  			return nil, fmt.Errorf("Unrecognized KeyDerivOpts provided [%s]", opts.Algorithm())
   198  
   199  		}
   200  	case *ecdsaPrivateKey:
   201  		// Validate opts
   202  		if opts == nil {
   203  			return nil, errors.New("Invalid Opts parameter. It must not be nil.")
   204  		}
   205  
   206  		ecdsaK := k.(*ecdsaPrivateKey)
   207  
   208  		switch opts.(type) {
   209  
   210  		// Re-randomized an ECDSA private key
   211  		case *bccsp.ECDSAReRandKeyOpts:
   212  			reRandOpts := opts.(*bccsp.ECDSAReRandKeyOpts)
   213  			pubKey := ecdsaK.pub.pub
   214  			if pubKey == nil {
   215  				return nil, errors.New("Public base key cannot be nil.")
   216  			}
   217  
   218  			secret := csp.getSecretValue(ecdsaK.ski)
   219  			if secret == nil {
   220  				return nil, errors.New("Could not obtain EC Private Key")
   221  			}
   222  			bigSecret := new(big.Int).SetBytes(secret)
   223  
   224  			tempSK := &ecdsa.PrivateKey{
   225  				PublicKey: ecdsa.PublicKey{
   226  					Curve: pubKey.Curve,
   227  					X:     new(big.Int),
   228  					Y:     new(big.Int),
   229  				},
   230  				D: new(big.Int),
   231  			}
   232  
   233  			var k = new(big.Int).SetBytes(reRandOpts.ExpansionValue())
   234  			var one = new(big.Int).SetInt64(1)
   235  			n := new(big.Int).Sub(pubKey.Params().N, one)
   236  			k.Mod(k, n)
   237  			k.Add(k, one)
   238  
   239  			tempSK.D.Add(bigSecret, k)
   240  			tempSK.D.Mod(tempSK.D, pubKey.Params().N)
   241  
   242  			// Compute temporary public key
   243  			tempSK.PublicKey.X, tempSK.PublicKey.Y = pubKey.ScalarBaseMult(tempSK.D.Bytes())
   244  
   245  			// Verify temporary public key is a valid point on the reference curve
   246  			isOn := tempSK.Curve.IsOnCurve(tempSK.PublicKey.X, tempSK.PublicKey.Y)
   247  			if !isOn {
   248  				return nil, errors.New("Failed temporary public key IsOnCurve check.")
   249  			}
   250  
   251  			ecPt := elliptic.Marshal(tempSK.Curve, tempSK.X, tempSK.Y)
   252  			oid, ok := oidFromNamedCurve(tempSK.Curve)
   253  			if !ok {
   254  				return nil, errors.New("Do not know OID for this Curve.")
   255  			}
   256  
   257  			ski, err := csp.importECKey(oid, tempSK.D.Bytes(), ecPt, opts.Ephemeral(), privateKeyFlag)
   258  			if err != nil {
   259  				return nil, fmt.Errorf("Failed getting importing EC Public Key [%s]", err)
   260  			}
   261  			reRandomizedKey := &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, &tempSK.PublicKey}}
   262  
   263  			return reRandomizedKey, nil
   264  
   265  		default:
   266  			return nil, fmt.Errorf("Unrecognized KeyDerivOpts provided [%s]", opts.Algorithm())
   267  
   268  		}
   269  
   270  	default:
   271  		return csp.BCCSP.KeyDeriv(k, opts)
   272  
   273  	}
   274  }
   275  
   276  // KeyImport imports a key from its raw representation using opts.
   277  // The opts argument should be appropriate for the primitive used.
   278  func (csp *impl) KeyImport(raw interface{}, opts bccsp.KeyImportOpts) (k bccsp.Key, err error) {
   279  	// Validate arguments
   280  	if raw == nil {
   281  		return nil, errors.New("Invalid raw. Cannot be nil.")
   282  	}
   283  
   284  	if opts == nil {
   285  		return nil, errors.New("Invalid Opts parameter. It must not be nil.")
   286  	}
   287  
   288  	switch opts.(type) {
   289  
   290  	case *bccsp.ECDSAPKIXPublicKeyImportOpts:
   291  		der, ok := raw.([]byte)
   292  		if !ok {
   293  			return nil, errors.New("[ECDSAPKIXPublicKeyImportOpts] Invalid raw material. Expected byte array.")
   294  		}
   295  
   296  		if len(der) == 0 {
   297  			return nil, errors.New("[ECDSAPKIXPublicKeyImportOpts] Invalid raw. It must not be nil.")
   298  		}
   299  
   300  		lowLevelKey, err := utils.DERToPublicKey(der)
   301  		if err != nil {
   302  			return nil, fmt.Errorf("Failed converting PKIX to ECDSA public key [%s]", err)
   303  		}
   304  
   305  		ecdsaPK, ok := lowLevelKey.(*ecdsa.PublicKey)
   306  		if !ok {
   307  			return nil, errors.New("Failed casting to ECDSA public key. Invalid raw material.")
   308  		}
   309  
   310  		ecPt := elliptic.Marshal(ecdsaPK.Curve, ecdsaPK.X, ecdsaPK.Y)
   311  		oid, ok := oidFromNamedCurve(ecdsaPK.Curve)
   312  		if !ok {
   313  			return nil, errors.New("Do not know OID for this Curve.")
   314  		}
   315  
   316  		var ski []byte
   317  		if csp.noPrivImport {
   318  			// opencryptoki does not support public ec key imports. This is a sufficient
   319  			// workaround for now to use soft verify
   320  			hash := sha256.Sum256(ecPt)
   321  			ski = hash[:]
   322  		} else {
   323  			// Warn about potential future problems
   324  			if !csp.softVerify {
   325  				logger.Debugf("opencryptoki workaround warning: Importing public EC Key does not store out to pkcs11 store,\n" +
   326  					"so verify with this key will fail, unless key is already present in store. Enable 'softwareverify'\n" +
   327  					"in pkcs11 options, if suspect this issue.")
   328  			}
   329  			ski, err = csp.importECKey(oid, nil, ecPt, opts.Ephemeral(), publicKeyFlag)
   330  			if err != nil {
   331  				return nil, fmt.Errorf("Failed getting importing EC Public Key [%s]", err)
   332  			}
   333  		}
   334  
   335  		k = &ecdsaPublicKey{ski, ecdsaPK}
   336  		return k, nil
   337  
   338  	case *bccsp.ECDSAPrivateKeyImportOpts:
   339  		if csp.noPrivImport {
   340  			return nil, errors.New("[ECDSADERPrivateKeyImportOpts] PKCS11 options 'sensitivekeys' is set to true. Cannot import.")
   341  		}
   342  
   343  		der, ok := raw.([]byte)
   344  		if !ok {
   345  			return nil, errors.New("[ECDSADERPrivateKeyImportOpts] Invalid raw material. Expected byte array.")
   346  		}
   347  
   348  		if len(der) == 0 {
   349  			return nil, errors.New("[ECDSADERPrivateKeyImportOpts] Invalid raw. It must not be nil.")
   350  		}
   351  
   352  		lowLevelKey, err := utils.DERToPrivateKey(der)
   353  		if err != nil {
   354  			return nil, fmt.Errorf("Failed converting PKIX to ECDSA public key [%s]", err)
   355  		}
   356  
   357  		ecdsaSK, ok := lowLevelKey.(*ecdsa.PrivateKey)
   358  		if !ok {
   359  			return nil, errors.New("Failed casting to ECDSA public key. Invalid raw material.")
   360  		}
   361  
   362  		ecPt := elliptic.Marshal(ecdsaSK.Curve, ecdsaSK.X, ecdsaSK.Y)
   363  		oid, ok := oidFromNamedCurve(ecdsaSK.Curve)
   364  		if !ok {
   365  			return nil, errors.New("Do not know OID for this Curve.")
   366  		}
   367  
   368  		ski, err := csp.importECKey(oid, ecdsaSK.D.Bytes(), ecPt, opts.Ephemeral(), privateKeyFlag)
   369  		if err != nil {
   370  			return nil, fmt.Errorf("Failed getting importing EC Private Key [%s]", err)
   371  		}
   372  
   373  		k = &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, &ecdsaSK.PublicKey}}
   374  		return k, nil
   375  
   376  	case *bccsp.ECDSAGoPublicKeyImportOpts:
   377  		lowLevelKey, ok := raw.(*ecdsa.PublicKey)
   378  		if !ok {
   379  			return nil, errors.New("[ECDSAGoPublicKeyImportOpts] Invalid raw material. Expected *ecdsa.PublicKey.")
   380  		}
   381  
   382  		ecPt := elliptic.Marshal(lowLevelKey.Curve, lowLevelKey.X, lowLevelKey.Y)
   383  		oid, ok := oidFromNamedCurve(lowLevelKey.Curve)
   384  		if !ok {
   385  			return nil, errors.New("Do not know OID for this Curve.")
   386  		}
   387  
   388  		var ski []byte
   389  		if csp.noPrivImport {
   390  			// opencryptoki does not support public ec key imports. This is a sufficient
   391  			// workaround for now to use soft verify
   392  			hash := sha256.Sum256(ecPt)
   393  			ski = hash[:]
   394  		} else {
   395  			// Warn about potential future problems
   396  			if !csp.softVerify {
   397  				logger.Debugf("opencryptoki workaround warning: Importing public EC Key does not store out to pkcs11 store,\n" +
   398  					"so verify with this key will fail, unless key is already present in store. Enable 'softwareverify'\n" +
   399  					"in pkcs11 options, if suspect this issue.")
   400  			}
   401  			ski, err = csp.importECKey(oid, nil, ecPt, opts.Ephemeral(), publicKeyFlag)
   402  			if err != nil {
   403  				return nil, fmt.Errorf("Failed getting importing EC Public Key [%s]", err)
   404  			}
   405  		}
   406  
   407  		k = &ecdsaPublicKey{ski, lowLevelKey}
   408  		return k, nil
   409  
   410  	case *bccsp.X509PublicKeyImportOpts:
   411  		x509Cert, ok := raw.(*x509.Certificate)
   412  		if !ok {
   413  			return nil, errors.New("[X509PublicKeyImportOpts] Invalid raw material. Expected *x509.Certificate.")
   414  		}
   415  
   416  		pk := x509Cert.PublicKey
   417  
   418  		switch pk.(type) {
   419  		case *ecdsa.PublicKey:
   420  			return csp.KeyImport(pk, &bccsp.ECDSAGoPublicKeyImportOpts{Temporary: opts.Ephemeral()})
   421  		case *rsa.PublicKey:
   422  			return csp.KeyImport(pk, &bccsp.RSAGoPublicKeyImportOpts{Temporary: opts.Ephemeral()})
   423  		default:
   424  			return nil, errors.New("Certificate's public key type not recognized. Supported keys: [ECDSA, RSA]")
   425  		}
   426  
   427  	default:
   428  		return csp.BCCSP.KeyImport(raw, opts)
   429  
   430  	}
   431  }
   432  
   433  // GetKey returns the key this CSP associates to
   434  // the Subject Key Identifier ski.
   435  func (csp *impl) GetKey(ski []byte) (k bccsp.Key, err error) {
   436  	pubKey, isPriv, err := csp.getECKey(ski)
   437  	if err == nil {
   438  		if isPriv {
   439  			return &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, pubKey}}, nil
   440  		} else {
   441  			return &ecdsaPublicKey{ski, pubKey}, nil
   442  		}
   443  	}
   444  	return csp.BCCSP.GetKey(ski)
   445  }
   446  
   447  // Sign signs digest using key k.
   448  // The opts argument should be appropriate for the primitive used.
   449  //
   450  // Note that when a signature of a hash of a larger message is needed,
   451  // the caller is responsible for hashing the larger message and passing
   452  // the hash (as digest).
   453  func (csp *impl) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) (signature []byte, err error) {
   454  	// Validate arguments
   455  	if k == nil {
   456  		return nil, errors.New("Invalid Key. It must not be nil.")
   457  	}
   458  	if len(digest) == 0 {
   459  		return nil, errors.New("Invalid digest. Cannot be empty.")
   460  	}
   461  
   462  	// Check key type
   463  	switch k.(type) {
   464  	case *ecdsaPrivateKey:
   465  		return csp.signECDSA(*k.(*ecdsaPrivateKey), digest, opts)
   466  	default:
   467  		return csp.BCCSP.Sign(k, digest, opts)
   468  	}
   469  }
   470  
   471  // Verify verifies signature against key k and digest
   472  func (csp *impl) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (valid bool, err error) {
   473  	// Validate arguments
   474  	if k == nil {
   475  		return false, errors.New("Invalid Key. It must not be nil.")
   476  	}
   477  	if len(signature) == 0 {
   478  		return false, errors.New("Invalid signature. Cannot be empty.")
   479  	}
   480  	if len(digest) == 0 {
   481  		return false, errors.New("Invalid digest. Cannot be empty.")
   482  	}
   483  
   484  	// Check key type
   485  	switch k.(type) {
   486  	case *ecdsaPrivateKey:
   487  		return csp.verifyECDSA(k.(*ecdsaPrivateKey).pub, signature, digest, opts)
   488  	case *ecdsaPublicKey:
   489  		return csp.verifyECDSA(*k.(*ecdsaPublicKey), signature, digest, opts)
   490  	default:
   491  		return csp.BCCSP.Verify(k, signature, digest, opts)
   492  	}
   493  }
   494  
   495  // Encrypt encrypts plaintext using key k.
   496  // The opts argument should be appropriate for the primitive used.
   497  func (csp *impl) Encrypt(k bccsp.Key, plaintext []byte, opts bccsp.EncrypterOpts) (ciphertext []byte, err error) {
   498  	// TODO: Add PKCS11 support for encryption, when fabric starts requiring it
   499  	return csp.BCCSP.Encrypt(k, plaintext, opts)
   500  }
   501  
   502  // Decrypt decrypts ciphertext using key k.
   503  // The opts argument should be appropriate for the primitive used.
   504  func (csp *impl) Decrypt(k bccsp.Key, ciphertext []byte, opts bccsp.DecrypterOpts) (plaintext []byte, err error) {
   505  	return csp.BCCSP.Decrypt(k, ciphertext, opts)
   506  }
   507  
   508  // THIS IS ONLY USED FOR TESTING
   509  // This is a convenience function. Useful to self-configure, for tests where usual configuration is not
   510  // available
   511  func FindPKCS11Lib() (lib, pin, label string) {
   512  	//FIXME: Till we workout the configuration piece, look for the libraries in the familiar places
   513  	lib = os.Getenv("PKCS11_LIB")
   514  	if lib == "" {
   515  		pin = "98765432"
   516  		label = "ForFabric"
   517  		possibilities := []string{
   518  			"/usr/lib/softhsm/libsofthsm2.so",                            //Debian
   519  			"/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so",           //Ubuntu
   520  			"/usr/lib/s390x-linux-gnu/softhsm/libsofthsm2.so",            //Ubuntu
   521  			"/usr/lib/powerpc64le-linux-gnu/softhsm/libsofthsm2.so",      //Power
   522  			"/usr/local/Cellar/softhsm/2.1.0/lib/softhsm/libsofthsm2.so", //MacOS
   523  		}
   524  		for _, path := range possibilities {
   525  			if _, err := os.Stat(path); !os.IsNotExist(err) {
   526  				lib = path
   527  				break
   528  			}
   529  		}
   530  	} else {
   531  		pin = os.Getenv("PKCS11_PIN")
   532  		label = os.Getenv("PKCS11_LABEL")
   533  	}
   534  	return lib, pin, label
   535  }