github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/bccsp/pkcs11/pkcs11_test.go (about)

     1  //go:build pkcs11
     2  // +build pkcs11
     3  
     4  /*
     5  Copyright hechain. All Rights Reserved.
     6  
     7  SPDX-License-Identifier: Apache-2.0
     8  */
     9  
    10  package pkcs11
    11  
    12  import (
    13  	"crypto/elliptic"
    14  	"crypto/rand"
    15  	"crypto/sha256"
    16  	"encoding/asn1"
    17  	"io/ioutil"
    18  	"os"
    19  	"strconv"
    20  	"strings"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/hechain20/hechain/bccsp"
    25  	"github.com/hechain20/hechain/bccsp/sw"
    26  	"github.com/hechain20/hechain/bccsp/utils"
    27  	"github.com/miekg/pkcs11"
    28  	"github.com/stretchr/testify/require"
    29  )
    30  
    31  func defaultOptions() PKCS11Opts {
    32  	lib, pin, label := FindPKCS11Lib()
    33  	return PKCS11Opts{
    34  		Library:                 lib,
    35  		Label:                   label,
    36  		Pin:                     pin,
    37  		Hash:                    "SHA2",
    38  		Security:                256,
    39  		SoftwareVerify:          false,
    40  		createSessionRetryDelay: time.Millisecond,
    41  	}
    42  }
    43  
    44  func newKeyStore(t *testing.T) (bccsp.KeyStore, func()) {
    45  	tempDir, err := ioutil.TempDir("", "pkcs11_ks")
    46  	require.NoError(t, err)
    47  	ks, err := sw.NewFileBasedKeyStore(nil, tempDir, false)
    48  	require.NoError(t, err)
    49  
    50  	return ks, func() { os.RemoveAll(tempDir) }
    51  }
    52  
    53  func newSWProvider(t *testing.T) bccsp.BCCSP {
    54  	ks, _ := newKeyStore(t)
    55  	swCsp, err := sw.NewDefaultSecurityLevelWithKeystore(ks)
    56  	require.NoError(t, err)
    57  
    58  	return swCsp
    59  }
    60  
    61  func newProvider(t *testing.T, opts PKCS11Opts, options ...Option) (*Provider, func()) {
    62  	ks, ksCleanup := newKeyStore(t)
    63  	csp, err := New(opts, ks, options...)
    64  	require.NoError(t, err)
    65  
    66  	cleanup := func() {
    67  		csp.ctx.Destroy()
    68  		ksCleanup()
    69  	}
    70  	return csp, cleanup
    71  }
    72  
    73  func TestNew(t *testing.T) {
    74  	ks, cleanup := newKeyStore(t)
    75  	defer cleanup()
    76  
    77  	t.Run("DefaultConfig", func(t *testing.T) {
    78  		opts := defaultOptions()
    79  		opts.createSessionRetryDelay = 0
    80  
    81  		csp, err := New(opts, ks)
    82  		require.NoError(t, err)
    83  		defer func() { csp.ctx.Destroy() }()
    84  
    85  		curve, err := curveForSecurityLevel(opts.Security)
    86  		require.NoError(t, err)
    87  
    88  		require.NotNil(t, csp.BCCSP)
    89  		require.Equal(t, opts.Pin, csp.pin)
    90  		require.NotNil(t, csp.ctx)
    91  		require.True(t, curve.Equal(csp.curve))
    92  		require.Equal(t, opts.SoftwareVerify, csp.softVerify)
    93  		require.Equal(t, opts.Immutable, csp.immutable)
    94  		require.Equal(t, defaultCreateSessionRetries, csp.createSessionRetries)
    95  		require.Equal(t, defaultCreateSessionRetryDelay, csp.createSessionRetryDelay)
    96  		require.Equal(t, defaultSessionCacheSize, cap(csp.sessPool))
    97  	})
    98  
    99  	t.Run("ConditionalOverride", func(t *testing.T) {
   100  		opts := defaultOptions()
   101  		opts.createSessionRetries = 3
   102  		opts.createSessionRetryDelay = time.Second
   103  		opts.sessionCacheSize = -1
   104  
   105  		csp, err := New(opts, ks)
   106  		require.NoError(t, err)
   107  		defer func() { csp.ctx.Destroy() }()
   108  
   109  		require.Equal(t, 3, csp.createSessionRetries)
   110  		require.Equal(t, time.Second, csp.createSessionRetryDelay)
   111  		require.Nil(t, csp.sessPool)
   112  	})
   113  }
   114  
   115  func TestInvalidNewParameter(t *testing.T) {
   116  	ks, cleanup := newKeyStore(t)
   117  	defer cleanup()
   118  
   119  	t.Run("BadSecurityLevel", func(t *testing.T) {
   120  		opts := defaultOptions()
   121  		opts.Security = 0
   122  
   123  		_, err := New(opts, ks)
   124  		require.EqualError(t, err, "Failed initializing configuration: Security level not supported [0]")
   125  	})
   126  
   127  	t.Run("BadHashFamily", func(t *testing.T) {
   128  		opts := defaultOptions()
   129  		opts.Hash = "SHA8"
   130  
   131  		_, err := New(opts, ks)
   132  		require.EqualError(t, err, "Failed initializing fallback SW BCCSP: Failed initializing configuration at [256,SHA8]: Hash Family not supported [SHA8]")
   133  	})
   134  
   135  	t.Run("BadKeyStore", func(t *testing.T) {
   136  		_, err := New(defaultOptions(), nil)
   137  		require.EqualError(t, err, "Failed initializing fallback SW BCCSP: Invalid bccsp.KeyStore instance. It must be different from nil.")
   138  	})
   139  
   140  	t.Run("MissingLibrary", func(t *testing.T) {
   141  		opts := defaultOptions()
   142  		opts.Library = ""
   143  
   144  		_, err := New(opts, ks)
   145  		require.Error(t, err)
   146  		require.Contains(t, err.Error(), "pkcs11: library path not provided")
   147  	})
   148  }
   149  
   150  func TestFindPKCS11LibEnvVars(t *testing.T) {
   151  	const (
   152  		dummy_PKCS11_LIB   = "/usr/lib/pkcs11"
   153  		dummy_PKCS11_PIN   = "23456789"
   154  		dummy_PKCS11_LABEL = "testing"
   155  	)
   156  
   157  	// Set environment variables used for test and preserve
   158  	// original values for restoration after test completion
   159  	orig_PKCS11_LIB := os.Getenv("PKCS11_LIB")
   160  	orig_PKCS11_PIN := os.Getenv("PKCS11_PIN")
   161  	orig_PKCS11_LABEL := os.Getenv("PKCS11_LABEL")
   162  
   163  	t.Run("ExplicitEnvironment", func(t *testing.T) {
   164  		os.Setenv("PKCS11_LIB", dummy_PKCS11_LIB)
   165  		os.Setenv("PKCS11_PIN", dummy_PKCS11_PIN)
   166  		os.Setenv("PKCS11_LABEL", dummy_PKCS11_LABEL)
   167  
   168  		lib, pin, label := FindPKCS11Lib()
   169  		require.EqualValues(t, dummy_PKCS11_LIB, lib, "FindPKCS11Lib did not return expected library")
   170  		require.EqualValues(t, dummy_PKCS11_PIN, pin, "FindPKCS11Lib did not return expected pin")
   171  		require.EqualValues(t, dummy_PKCS11_LABEL, label, "FindPKCS11Lib did not return expected label")
   172  	})
   173  
   174  	t.Run("MissingEnvironment", func(t *testing.T) {
   175  		os.Unsetenv("PKCS11_LIB")
   176  		os.Unsetenv("PKCS11_PIN")
   177  		os.Unsetenv("PKCS11_LABEL")
   178  
   179  		_, pin, label := FindPKCS11Lib()
   180  		require.EqualValues(t, "98765432", pin, "FindPKCS11Lib did not return expected pin")
   181  		require.EqualValues(t, "ForFabric", label, "FindPKCS11Lib did not return expected label")
   182  	})
   183  
   184  	os.Setenv("PKCS11_LIB", orig_PKCS11_LIB)
   185  	os.Setenv("PKCS11_PIN", orig_PKCS11_PIN)
   186  	os.Setenv("PKCS11_LABEL", orig_PKCS11_LABEL)
   187  }
   188  
   189  func TestInvalidSKI(t *testing.T) {
   190  	csp, cleanup := newProvider(t, defaultOptions())
   191  	defer cleanup()
   192  
   193  	_, err := csp.GetKey(nil)
   194  	require.EqualError(t, err, "Failed getting key for SKI [[]]: invalid SKI. Cannot be of zero length")
   195  
   196  	_, err = csp.GetKey([]byte{0, 1, 2, 3, 4, 5, 6})
   197  	require.Error(t, err)
   198  	require.True(t, strings.HasPrefix(err.Error(), "Failed getting key for SKI [[0 1 2 3 4 5 6]]: "))
   199  }
   200  
   201  func TestKeyGenECDSAOpts(t *testing.T) {
   202  	tests := map[string]struct {
   203  		curve     elliptic.Curve
   204  		immutable bool
   205  		opts      bccsp.KeyGenOpts
   206  	}{
   207  		"Default":             {elliptic.P256(), false, &bccsp.ECDSAKeyGenOpts{Temporary: false}},
   208  		"P256":                {elliptic.P256(), false, &bccsp.ECDSAP256KeyGenOpts{Temporary: false}},
   209  		"P384":                {elliptic.P384(), false, &bccsp.ECDSAP384KeyGenOpts{Temporary: false}},
   210  		"Immutable":           {elliptic.P384(), true, &bccsp.ECDSAP384KeyGenOpts{Temporary: false}},
   211  		"Ephemeral/Default":   {elliptic.P256(), false, &bccsp.ECDSAKeyGenOpts{Temporary: true}},
   212  		"Ephemeral/P256":      {elliptic.P256(), false, &bccsp.ECDSAP256KeyGenOpts{Temporary: true}},
   213  		"Ephemeral/P384":      {elliptic.P384(), false, &bccsp.ECDSAP384KeyGenOpts{Temporary: true}},
   214  		"Ephemeral/Immutable": {elliptic.P384(), true, &bccsp.ECDSAP384KeyGenOpts{Temporary: false}},
   215  	}
   216  	for name, tt := range tests {
   217  		t.Run(name, func(t *testing.T) {
   218  			opts := defaultOptions()
   219  			opts.Immutable = tt.immutable
   220  			csp, cleanup := newProvider(t, opts)
   221  			defer cleanup()
   222  
   223  			k, err := csp.KeyGen(tt.opts)
   224  			require.NoError(t, err)
   225  			require.True(t, k.Private(), "key should be private")
   226  			require.False(t, k.Symmetric(), "key should be asymmetric")
   227  
   228  			ecdsaKey := k.(*ecdsaPrivateKey).pub
   229  			require.Equal(t, tt.curve, ecdsaKey.pub.Curve, "wrong curve")
   230  
   231  			raw, err := k.Bytes()
   232  			require.EqualError(t, err, "Not supported.")
   233  			require.Empty(t, raw, "result should be empty")
   234  
   235  			pk, err := k.PublicKey()
   236  			require.NoError(t, err)
   237  			require.NotNil(t, pk)
   238  
   239  			sess, err := csp.getSession()
   240  			require.NoError(t, err)
   241  			defer csp.returnSession(sess)
   242  
   243  			for _, kt := range []keyType{publicKeyType, privateKeyType} {
   244  				handle, err := csp.findKeyPairFromSKI(sess, k.SKI(), kt)
   245  				require.NoError(t, err)
   246  
   247  				attr, err := csp.ctx.GetAttributeValue(sess, handle, []*pkcs11.Attribute{{Type: pkcs11.CKA_TOKEN}})
   248  				require.NoError(t, err)
   249  				require.Len(t, attr, 1)
   250  
   251  				if tt.opts.Ephemeral() {
   252  					require.Equal(t, []byte{0}, attr[0].Value)
   253  				} else {
   254  					require.Equal(t, []byte{1}, attr[0].Value)
   255  				}
   256  
   257  				attr, err = csp.ctx.GetAttributeValue(sess, handle, []*pkcs11.Attribute{{Type: pkcs11.CKA_MODIFIABLE}})
   258  				require.NoError(t, err)
   259  				require.Len(t, attr, 1)
   260  
   261  				if tt.immutable {
   262  					require.Equal(t, []byte{0}, attr[0].Value)
   263  				} else {
   264  					require.Equal(t, []byte{1}, attr[0].Value)
   265  				}
   266  			}
   267  		})
   268  	}
   269  }
   270  
   271  func TestKeyGenMissingOpts(t *testing.T) {
   272  	csp, cleanup := newProvider(t, defaultOptions())
   273  	defer cleanup()
   274  
   275  	_, err := csp.KeyGen(bccsp.KeyGenOpts(nil))
   276  	require.Error(t, err)
   277  	require.Contains(t, err.Error(), "Invalid Opts parameter. It must not be nil")
   278  }
   279  
   280  func TestECDSAGetKeyBySKI(t *testing.T) {
   281  	csp, cleanup := newProvider(t, defaultOptions())
   282  	defer cleanup()
   283  
   284  	k, err := csp.KeyGen(&bccsp.ECDSAKeyGenOpts{Temporary: false})
   285  	require.NoError(t, err)
   286  
   287  	k2, err := csp.GetKey(k.SKI())
   288  	require.NoError(t, err)
   289  
   290  	require.True(t, k2.Private(), "key should be private")
   291  	require.False(t, k2.Symmetric(), "key should be asymmetric")
   292  	require.Equalf(t, k.SKI(), k2.SKI(), "expected %x got %x", k.SKI(), k2.SKI())
   293  }
   294  
   295  func TestECDSAPublicKeyFromPrivateKey(t *testing.T) {
   296  	csp, cleanup := newProvider(t, defaultOptions())
   297  	defer cleanup()
   298  
   299  	k, err := csp.KeyGen(&bccsp.ECDSAKeyGenOpts{Temporary: false})
   300  	require.NoError(t, err)
   301  
   302  	pk, err := k.PublicKey()
   303  	require.NoError(t, err)
   304  	require.False(t, pk.Private(), "key should be public")
   305  	require.False(t, pk.Symmetric(), "key should be asymmetric")
   306  	require.Equal(t, k.SKI(), pk.SKI(), "SKI should be the same")
   307  
   308  	raw, err := pk.Bytes()
   309  	require.NoError(t, err)
   310  	require.NotEmpty(t, raw, "marshaled ECDSA public key must not be empty")
   311  }
   312  
   313  func TestECDSASign(t *testing.T) {
   314  	csp, cleanup := newProvider(t, defaultOptions())
   315  	defer cleanup()
   316  
   317  	k, err := csp.KeyGen(&bccsp.ECDSAKeyGenOpts{Temporary: false})
   318  	require.NoError(t, err)
   319  
   320  	digest, err := csp.Hash([]byte("Hello World"), &bccsp.SHAOpts{})
   321  	require.NoError(t, err)
   322  
   323  	signature, err := csp.Sign(k, digest, nil)
   324  	require.NoError(t, err)
   325  	require.NotEmpty(t, signature, "signature must not be empty")
   326  
   327  	t.Run("NoKey", func(t *testing.T) {
   328  		_, err := csp.Sign(nil, digest, nil)
   329  		require.Error(t, err)
   330  		require.Contains(t, err.Error(), "Invalid Key. It must not be nil")
   331  	})
   332  
   333  	t.Run("BadSKI", func(t *testing.T) {
   334  		_, err := csp.Sign(&ecdsaPrivateKey{ski: []byte("bad-ski")}, digest, nil)
   335  		require.Error(t, err)
   336  		require.Contains(t, err.Error(), "Private key not found")
   337  	})
   338  
   339  	t.Run("MissingDigest", func(t *testing.T) {
   340  		_, err = csp.Sign(k, nil, nil)
   341  		require.Error(t, err)
   342  		require.Contains(t, err.Error(), "Invalid digest. Cannot be empty")
   343  	})
   344  }
   345  
   346  type mapper struct {
   347  	input  []byte
   348  	result []byte
   349  }
   350  
   351  func (m *mapper) skiToID(ski []byte) []byte {
   352  	m.input = ski
   353  	return m.result
   354  }
   355  
   356  func TestKeyMapper(t *testing.T) {
   357  	mapper := &mapper{}
   358  	csp, cleanup := newProvider(t, defaultOptions(), WithKeyMapper(mapper.skiToID))
   359  	defer cleanup()
   360  
   361  	k, err := csp.KeyGen(&bccsp.ECDSAKeyGenOpts{Temporary: false})
   362  	require.NoError(t, err)
   363  
   364  	digest, err := csp.Hash([]byte("Hello World"), &bccsp.SHAOpts{})
   365  	require.NoError(t, err)
   366  
   367  	sess, err := csp.getSession()
   368  	require.NoError(t, err, "failed to get session")
   369  	defer csp.returnSession(sess)
   370  
   371  	newID := []byte("mapped-id")
   372  	updateKeyIdentifier(t, csp.ctx, sess, pkcs11.CKO_PUBLIC_KEY, k.SKI(), newID)
   373  	updateKeyIdentifier(t, csp.ctx, sess, pkcs11.CKO_PRIVATE_KEY, k.SKI(), newID)
   374  
   375  	t.Run("ToMissingID", func(t *testing.T) {
   376  		csp.clearCaches()
   377  		mapper.result = k.SKI()
   378  		_, err := csp.Sign(k, digest, nil)
   379  		require.ErrorContains(t, err, "Private key not found")
   380  		require.Equal(t, k.SKI(), mapper.input, "expected mapper to receive ski %x, got %x", k.SKI(), mapper.input)
   381  	})
   382  	t.Run("ToNewID", func(t *testing.T) {
   383  		csp.clearCaches()
   384  		mapper.result = newID
   385  		signature, err := csp.Sign(k, digest, nil)
   386  		require.NoError(t, err)
   387  		require.NotEmpty(t, signature, "signature must not be empty")
   388  		require.Equal(t, k.SKI(), mapper.input, "expected mapper to receive ski %x, got %x", k.SKI(), mapper.input)
   389  	})
   390  }
   391  
   392  func updateKeyIdentifier(t *testing.T, pctx *pkcs11.Ctx, sess pkcs11.SessionHandle, class uint, currentID, newID []byte) {
   393  	pkt := []*pkcs11.Attribute{
   394  		pkcs11.NewAttribute(pkcs11.CKA_CLASS, class),
   395  		pkcs11.NewAttribute(pkcs11.CKA_ID, currentID),
   396  	}
   397  	err := pctx.FindObjectsInit(sess, pkt)
   398  	require.NoError(t, err)
   399  
   400  	objs, _, err := pctx.FindObjects(sess, 1)
   401  	require.NoError(t, err)
   402  	require.Len(t, objs, 1)
   403  
   404  	err = pctx.FindObjectsFinal(sess)
   405  	require.NoError(t, err)
   406  
   407  	err = pctx.SetAttributeValue(sess, objs[0], []*pkcs11.Attribute{
   408  		pkcs11.NewAttribute(pkcs11.CKA_ID, newID),
   409  	})
   410  	require.NoError(t, err)
   411  }
   412  
   413  func TestVerify(t *testing.T) {
   414  	pkcs11CSP, cleanup := newProvider(t, defaultOptions())
   415  	defer cleanup()
   416  
   417  	digest, err := pkcs11CSP.Hash([]byte("Hello, World."), &bccsp.SHAOpts{})
   418  	require.NoError(t, err)
   419  	otherDigest, err := pkcs11CSP.Hash([]byte("Bye, World."), &bccsp.SHAOpts{})
   420  	require.NoError(t, err)
   421  
   422  	pkcs11Key, err := pkcs11CSP.KeyGen(&bccsp.ECDSAKeyGenOpts{Temporary: true})
   423  	require.NoError(t, err)
   424  	pkcs11PublicKey, err := pkcs11Key.PublicKey()
   425  	require.NoError(t, err)
   426  	b, err := pkcs11PublicKey.Bytes()
   427  	require.NoError(t, err)
   428  
   429  	swCSP := newSWProvider(t)
   430  	swKey, err := swCSP.KeyImport(b, &bccsp.ECDSAPKIXPublicKeyImportOpts{Temporary: false})
   431  	require.NoError(t, err)
   432  
   433  	signature, err := pkcs11CSP.Sign(pkcs11Key, digest, nil)
   434  	require.NoError(t, err)
   435  
   436  	swPublicKey, err := swKey.PublicKey()
   437  	require.NoError(t, err)
   438  
   439  	valid, err := pkcs11CSP.Verify(swPublicKey, signature, digest, nil)
   440  	require.NoError(t, err)
   441  	require.True(t, valid, "signature should be valid from software public key")
   442  
   443  	valid, err = pkcs11CSP.Verify(swPublicKey, signature, otherDigest, nil)
   444  	require.NoError(t, err)
   445  	require.False(t, valid, "signature should not be valid from software public key")
   446  
   447  	valid, err = pkcs11CSP.Verify(pkcs11Key, signature, digest, nil)
   448  	require.Error(t, err)
   449  	require.False(t, valid, "Verify should not handle a pkcs11 key")
   450  }
   451  
   452  func TestECDSAVerify(t *testing.T) {
   453  	csp, cleanup := newProvider(t, defaultOptions())
   454  	defer cleanup()
   455  
   456  	k, err := csp.KeyGen(&bccsp.ECDSAKeyGenOpts{Temporary: false})
   457  	require.NoError(t, err)
   458  	pk, err := k.PublicKey()
   459  	require.NoError(t, err)
   460  
   461  	digest, err := csp.Hash([]byte("Hello, World."), &bccsp.SHAOpts{})
   462  	require.NoError(t, err)
   463  	otherDigest, err := csp.Hash([]byte("Bye, World."), &bccsp.SHAOpts{})
   464  	require.NoError(t, err)
   465  
   466  	signature, err := csp.Sign(k, digest, nil)
   467  	require.NoError(t, err)
   468  
   469  	tests := map[string]bool{
   470  		"WithSoftVerify":    true,
   471  		"WithoutSoftVerify": false,
   472  	}
   473  
   474  	pkcs11PublicKey := pk.(*ecdsaPublicKey)
   475  
   476  	for name, softVerify := range tests {
   477  		t.Run(name, func(t *testing.T) {
   478  			opts := defaultOptions()
   479  			opts.SoftwareVerify = softVerify
   480  			csp, cleanup := newProvider(t, opts)
   481  			defer cleanup()
   482  
   483  			valid, err := csp.verifyECDSA(*pkcs11PublicKey, signature, digest)
   484  			require.NoError(t, err)
   485  			require.True(t, valid, "signature should be valid from public key")
   486  
   487  			valid, err = csp.verifyECDSA(*pkcs11PublicKey, signature, otherDigest)
   488  			require.NoError(t, err)
   489  			require.False(t, valid, "signature should not be valid from public key")
   490  		})
   491  	}
   492  
   493  	t.Run("MissingKey", func(t *testing.T) {
   494  		_, err := csp.Verify(nil, signature, digest, nil)
   495  		require.Error(t, err)
   496  		require.Contains(t, err.Error(), "Invalid Key. It must not be nil")
   497  	})
   498  
   499  	t.Run("MissingSignature", func(t *testing.T) {
   500  		_, err := csp.Verify(pk, nil, digest, nil)
   501  		require.Error(t, err)
   502  		require.Contains(t, err.Error(), "Invalid signature. Cannot be empty")
   503  	})
   504  
   505  	t.Run("MissingDigest", func(t *testing.T) {
   506  		_, err = csp.Verify(pk, signature, nil, nil)
   507  		require.Error(t, err)
   508  		require.Contains(t, err.Error(), "Invalid digest. Cannot be empty")
   509  	})
   510  }
   511  
   512  func TestECDSALowS(t *testing.T) {
   513  	csp, cleanup := newProvider(t, defaultOptions())
   514  	defer cleanup()
   515  
   516  	k, err := csp.KeyGen(&bccsp.ECDSAKeyGenOpts{Temporary: false})
   517  	require.NoError(t, err)
   518  
   519  	digest, err := csp.Hash([]byte("Hello World"), &bccsp.SHAOpts{})
   520  	require.NoError(t, err)
   521  
   522  	// Ensure that signature with low-S are generated
   523  	t.Run("GeneratesLowS", func(t *testing.T) {
   524  		signature, err := csp.Sign(k, digest, nil)
   525  		require.NoError(t, err)
   526  
   527  		_, S, err := utils.UnmarshalECDSASignature(signature)
   528  		require.NoError(t, err)
   529  
   530  		if S.Cmp(utils.GetCurveHalfOrdersAt(k.(*ecdsaPrivateKey).pub.pub.Curve)) >= 0 {
   531  			t.Fatal("Invalid signature. It must have low-S")
   532  		}
   533  
   534  		pk, err := k.PublicKey()
   535  		require.NoError(t, err)
   536  
   537  		valid, err := csp.verifyECDSA(*(pk.(*ecdsaPublicKey)), signature, digest)
   538  		require.NoError(t, err)
   539  		require.True(t, valid, "signature should be valid")
   540  	})
   541  
   542  	// Ensure that signature with high-S are rejected.
   543  	t.Run("RejectsHighS", func(t *testing.T) {
   544  		for {
   545  			R, S, err := csp.signP11ECDSA(k.SKI(), digest)
   546  			require.NoError(t, err)
   547  			if S.Cmp(utils.GetCurveHalfOrdersAt(k.(*ecdsaPrivateKey).pub.pub.Curve)) > 0 {
   548  				sig, err := utils.MarshalECDSASignature(R, S)
   549  				require.NoError(t, err)
   550  
   551  				valid, err := csp.Verify(k, sig, digest, nil)
   552  				require.Error(t, err, "verification must fail for a signature with high-S")
   553  				require.False(t, valid, "signature must not be valid with high-S")
   554  				return
   555  			}
   556  		}
   557  	})
   558  }
   559  
   560  func TestInitialize(t *testing.T) {
   561  	// Setup PKCS11 library and provide initial set of values
   562  	lib, pin, label := FindPKCS11Lib()
   563  
   564  	t.Run("MissingLibrary", func(t *testing.T) {
   565  		_, err := (&Provider{}).initialize(PKCS11Opts{Library: "", Pin: pin, Label: label})
   566  		require.Error(t, err)
   567  		require.Contains(t, err.Error(), "pkcs11: library path not provided")
   568  	})
   569  
   570  	t.Run("BadLibraryPath", func(t *testing.T) {
   571  		_, err := (&Provider{}).initialize(PKCS11Opts{Library: "badLib", Pin: pin, Label: label})
   572  		require.Error(t, err)
   573  		require.Contains(t, err.Error(), "pkcs11: instantiation failed for badLib")
   574  	})
   575  
   576  	t.Run("BadLabel", func(t *testing.T) {
   577  		_, err := (&Provider{}).initialize(PKCS11Opts{Library: lib, Pin: pin, Label: "badLabel"})
   578  		require.Error(t, err)
   579  		require.Contains(t, err.Error(), "could not find token with label")
   580  	})
   581  
   582  	t.Run("MissingPin", func(t *testing.T) {
   583  		_, err := (&Provider{}).initialize(PKCS11Opts{Library: lib, Pin: "", Label: label})
   584  		require.Error(t, err)
   585  		require.Contains(t, err.Error(), "Login failed: pkcs11")
   586  	})
   587  }
   588  
   589  func TestNamedCurveFromOID(t *testing.T) {
   590  	tests := map[string]struct {
   591  		oid   asn1.ObjectIdentifier
   592  		curve elliptic.Curve
   593  	}{
   594  		"P224":    {oidNamedCurveP224, elliptic.P224()},
   595  		"P256":    {oidNamedCurveP256, elliptic.P256()},
   596  		"P384":    {oidNamedCurveP384, elliptic.P384()},
   597  		"P521":    {oidNamedCurveP521, elliptic.P521()},
   598  		"unknown": {asn1.ObjectIdentifier{4, 9, 15, 1}, nil},
   599  	}
   600  
   601  	for name, tt := range tests {
   602  		t.Run(name, func(t *testing.T) {
   603  			require.Equal(t, tt.curve, namedCurveFromOID(tt.oid))
   604  		})
   605  	}
   606  }
   607  
   608  func TestCurveForSecurityLevel(t *testing.T) {
   609  	tests := map[int]struct {
   610  		expectedErr string
   611  		curve       asn1.ObjectIdentifier
   612  	}{
   613  		256: {curve: oidNamedCurveP256},
   614  		384: {curve: oidNamedCurveP384},
   615  		512: {expectedErr: "Security level not supported [512]"},
   616  	}
   617  
   618  	for level, tt := range tests {
   619  		t.Run(strconv.Itoa(level), func(t *testing.T) {
   620  			curve, err := curveForSecurityLevel(level)
   621  			if tt.expectedErr != "" {
   622  				require.EqualError(t, err, tt.expectedErr)
   623  				return
   624  			}
   625  			require.NoError(t, err)
   626  			require.Equal(t, tt.curve, curve)
   627  		})
   628  	}
   629  }
   630  
   631  func TestPKCS11GetSession(t *testing.T) {
   632  	opts := defaultOptions()
   633  	opts.sessionCacheSize = 5
   634  	csp, cleanup := newProvider(t, opts)
   635  	defer cleanup()
   636  
   637  	sessionCacheSize := opts.sessionCacheSize
   638  	var sessions []pkcs11.SessionHandle
   639  	for i := 0; i < 3*sessionCacheSize; i++ {
   640  		session, err := csp.getSession()
   641  		require.NoError(t, err)
   642  		sessions = append(sessions, session)
   643  	}
   644  
   645  	// Return all sessions, should leave sessionCacheSize cached
   646  	for _, session := range sessions {
   647  		csp.returnSession(session)
   648  	}
   649  
   650  	// Should be able to get sessionCacheSize cached sessions
   651  	sessions = nil
   652  	for i := 0; i < sessionCacheSize; i++ {
   653  		session, err := csp.getSession()
   654  		require.NoError(t, err)
   655  		sessions = append(sessions, session)
   656  	}
   657  
   658  	// Cleanup
   659  	for _, session := range sessions {
   660  		csp.returnSession(session)
   661  	}
   662  }
   663  
   664  func TestSessionHandleCaching(t *testing.T) {
   665  	verifyHandleCache := func(t *testing.T, csp *Provider, sess pkcs11.SessionHandle, k bccsp.Key) {
   666  		pubHandle, err := csp.findKeyPairFromSKI(sess, k.SKI(), publicKeyType)
   667  		require.NoError(t, err)
   668  		h, ok := csp.cachedHandle(publicKeyType, k.SKI())
   669  		require.True(t, ok)
   670  		require.Equal(t, h, pubHandle)
   671  
   672  		privHandle, err := csp.findKeyPairFromSKI(sess, k.SKI(), privateKeyType)
   673  		require.NoError(t, err)
   674  		h, ok = csp.cachedHandle(privateKeyType, k.SKI())
   675  		require.True(t, ok)
   676  		require.Equal(t, h, privHandle)
   677  	}
   678  
   679  	t.Run("SessionCacheDisabled", func(t *testing.T) {
   680  		opts := defaultOptions()
   681  		opts.sessionCacheSize = -1
   682  
   683  		csp, cleanup := newProvider(t, opts)
   684  		defer cleanup()
   685  
   686  		require.Nil(t, csp.sessPool, "sessPool channel should be nil")
   687  		require.Empty(t, csp.sessions, "sessions set should be empty")
   688  		require.Empty(t, csp.handleCache, "handleCache should be empty")
   689  
   690  		sess1, err := csp.getSession()
   691  		require.NoError(t, err)
   692  		require.Len(t, csp.sessions, 1, "expected one open session")
   693  
   694  		sess2, err := csp.getSession()
   695  		require.NoError(t, err)
   696  		require.Len(t, csp.sessions, 2, "expected two open sessions")
   697  
   698  		// Generate a key
   699  		k, err := csp.KeyGen(&bccsp.ECDSAP256KeyGenOpts{Temporary: false})
   700  		require.NoError(t, err)
   701  		verifyHandleCache(t, csp, sess1, k)
   702  		require.Len(t, csp.handleCache, 2, "expected two handles in handle cache")
   703  
   704  		csp.returnSession(sess1)
   705  		require.Len(t, csp.sessions, 1, "expected one open session")
   706  		verifyHandleCache(t, csp, sess1, k)
   707  		require.Len(t, csp.handleCache, 2, "expected two handles in handle cache")
   708  
   709  		csp.returnSession(sess2)
   710  		require.Empty(t, csp.sessions, "expected sessions to be empty")
   711  		require.Empty(t, csp.handleCache, "expected handles to be cleared")
   712  	})
   713  
   714  	t.Run("SessionCacheEnabled", func(t *testing.T) {
   715  		opts := defaultOptions()
   716  		opts.sessionCacheSize = 1
   717  
   718  		csp, cleanup := newProvider(t, opts)
   719  		defer cleanup()
   720  
   721  		require.NotNil(t, csp.sessPool, "sessPool channel should not be nil")
   722  		require.Equal(t, 1, cap(csp.sessPool))
   723  		require.Len(t, csp.sessions, 1, "sessions should contain login session")
   724  		require.Len(t, csp.sessPool, 1, "sessionPool should hold login session")
   725  		require.Empty(t, csp.handleCache, "handleCache should be empty")
   726  
   727  		sess1, err := csp.getSession()
   728  		require.NoError(t, err)
   729  		require.Len(t, csp.sessions, 1, "expected one open session (sess1 from login)")
   730  		require.Len(t, csp.sessPool, 0, "sessionPool should be empty")
   731  
   732  		sess2, err := csp.getSession()
   733  		require.NoError(t, err)
   734  		require.Len(t, csp.sessions, 2, "expected two open sessions (sess1 and sess2)")
   735  		require.Len(t, csp.sessPool, 0, "sessionPool should be empty")
   736  
   737  		// Generate a key
   738  		k, err := csp.KeyGen(&bccsp.ECDSAP256KeyGenOpts{Temporary: false})
   739  		require.NoError(t, err)
   740  		verifyHandleCache(t, csp, sess1, k)
   741  		require.Len(t, csp.handleCache, 2, "expected two handles in handle cache")
   742  
   743  		csp.returnSession(sess1)
   744  		require.Len(t, csp.sessions, 2, "expected two open sessions (sess2 in-use, sess1 cached)")
   745  		require.Len(t, csp.sessPool, 1, "sessionPool should have one handle (sess1)")
   746  		verifyHandleCache(t, csp, sess1, k)
   747  		require.Len(t, csp.handleCache, 2, "expected two handles in handle cache")
   748  
   749  		csp.returnSession(sess2)
   750  		require.Len(t, csp.sessions, 1, "expected one cached session (sess1)")
   751  		require.Len(t, csp.sessPool, 1, "sessionPool should have one handle (sess1)")
   752  		require.Len(t, csp.handleCache, 2, "expected two handles in handle cache")
   753  
   754  		_, err = csp.getSession()
   755  		require.NoError(t, err)
   756  		require.Len(t, csp.sessions, 1, "expected one open session (sess1)")
   757  		require.Len(t, csp.sessPool, 0, "sessionPool should be empty")
   758  		require.Len(t, csp.handleCache, 2, "expected two handles in handle cache")
   759  	})
   760  }
   761  
   762  func TestKeyCache(t *testing.T) {
   763  	opts := defaultOptions()
   764  	opts.sessionCacheSize = 1
   765  	csp, cleanup := newProvider(t, opts)
   766  	defer cleanup()
   767  
   768  	require.Empty(t, csp.keyCache)
   769  
   770  	_, err := csp.GetKey([]byte("nonsense-key"))
   771  	require.Error(t, err) // message comes from software keystore
   772  	require.Empty(t, csp.keyCache)
   773  
   774  	k, err := csp.KeyGen(&bccsp.ECDSAP256KeyGenOpts{Temporary: false})
   775  	require.NoError(t, err)
   776  	_, ok := csp.cachedKey(k.SKI())
   777  	require.False(t, ok, "created keys are not (currently) cached")
   778  
   779  	key, err := csp.GetKey(k.SKI())
   780  	require.NoError(t, err)
   781  	cached, ok := csp.cachedKey(k.SKI())
   782  	require.True(t, ok, "key should be cached")
   783  	require.Same(t, key, cached, "key from cache should be what was found")
   784  
   785  	// Retrieve last session
   786  	sess, err := csp.getSession()
   787  	require.NoError(t, err)
   788  	require.Empty(t, csp.sessPool, "sessionPool should be empty")
   789  
   790  	// Force caches to be cleared by closing last session
   791  	csp.closeSession(sess)
   792  	require.Empty(t, csp.sessions, "sessions should be empty")
   793  	require.Empty(t, csp.keyCache, "key cache should be empty")
   794  
   795  	_, ok = csp.cachedKey(k.SKI())
   796  	require.False(t, ok, "key should not be in cache")
   797  }
   798  
   799  // This helps verify that we're delegating to the software provider.
   800  // This is not intended to test the software provider implementation.
   801  func TestDelegation(t *testing.T) {
   802  	csp, cleanup := newProvider(t, defaultOptions())
   803  	defer cleanup()
   804  
   805  	k, err := csp.KeyGen(&bccsp.AES256KeyGenOpts{})
   806  	require.NoError(t, err)
   807  
   808  	t.Run("KeyGen", func(t *testing.T) {
   809  		k, err := csp.KeyGen(&bccsp.AES256KeyGenOpts{})
   810  		require.NoError(t, err)
   811  		require.True(t, k.Private())
   812  		require.True(t, k.Symmetric())
   813  	})
   814  
   815  	t.Run("KeyDeriv", func(t *testing.T) {
   816  		k, err := csp.KeyDeriv(k, &bccsp.HMACDeriveKeyOpts{Arg: []byte{1}})
   817  		require.NoError(t, err)
   818  		require.True(t, k.Private())
   819  	})
   820  
   821  	t.Run("KeyImport", func(t *testing.T) {
   822  		raw := make([]byte, 32)
   823  		_, err := rand.Read(raw)
   824  		require.NoError(t, err)
   825  
   826  		k, err := csp.KeyImport(raw, &bccsp.AES256ImportKeyOpts{})
   827  		require.NoError(t, err)
   828  		require.True(t, k.Private())
   829  	})
   830  
   831  	t.Run("GetKey", func(t *testing.T) {
   832  		k, err := csp.GetKey(k.SKI())
   833  		require.NoError(t, err)
   834  		require.True(t, k.Private())
   835  	})
   836  
   837  	t.Run("Hash", func(t *testing.T) {
   838  		digest, err := csp.Hash([]byte("message"), &bccsp.SHA3_384Opts{})
   839  		require.NoError(t, err)
   840  		require.NotEmpty(t, digest)
   841  	})
   842  
   843  	t.Run("GetHash", func(t *testing.T) {
   844  		h, err := csp.GetHash(&bccsp.SHA256Opts{})
   845  		require.NoError(t, err)
   846  		require.Equal(t, sha256.New(), h)
   847  	})
   848  
   849  	t.Run("Sign", func(t *testing.T) {
   850  		_, err := csp.Sign(k, []byte("message"), nil)
   851  		require.EqualError(t, err, "Unsupported 'SignKey' provided [*sw.aesPrivateKey]")
   852  	})
   853  
   854  	t.Run("Verify", func(t *testing.T) {
   855  		_, err := csp.Verify(k, []byte("signature"), []byte("digest"), nil)
   856  		require.Error(t, err)
   857  		require.Contains(t, err.Error(), "Unsupported 'VerifyKey' provided")
   858  	})
   859  
   860  	t.Run("EncryptDecrypt", func(t *testing.T) {
   861  		msg := []byte("message")
   862  		ct, err := csp.Encrypt(k, msg, &bccsp.AESCBCPKCS7ModeOpts{})
   863  		require.NoError(t, err)
   864  
   865  		pt, err := csp.Decrypt(k, ct, &bccsp.AESCBCPKCS7ModeOpts{})
   866  		require.NoError(t, err)
   867  		require.Equal(t, msg, pt)
   868  	})
   869  }
   870  
   871  func TestHandleSessionReturn(t *testing.T) {
   872  	opts := defaultOptions()
   873  	opts.sessionCacheSize = 5
   874  	csp, cleanup := newProvider(t, opts)
   875  	defer cleanup()
   876  
   877  	// Retrieve and destroy default session created during initialization
   878  	session, err := csp.getSession()
   879  	require.NoError(t, err)
   880  	csp.closeSession(session)
   881  
   882  	// Verify session pool is empty and place invalid session in pool
   883  	require.Empty(t, csp.sessPool, "sessionPool should be empty")
   884  	csp.returnSession(pkcs11.SessionHandle(^uint(0)))
   885  
   886  	// Attempt to generate key with invalid session
   887  	_, err = csp.KeyGen(&bccsp.ECDSAP256KeyGenOpts{Temporary: false})
   888  	require.EqualError(t, err, "Failed generating ECDSA P256 key: P11: keypair generate failed [pkcs11: 0xB3: CKR_SESSION_HANDLE_INVALID]")
   889  	require.Empty(t, csp.sessPool, "sessionPool should be empty")
   890  }