github.com/kchristidis/fabric@v1.0.4-0.20171028114726-837acd08cde1/bccsp/pkcs11/pkcs11_test.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/rand"
    22  	"encoding/asn1"
    23  	"encoding/hex"
    24  	"testing"
    25  
    26  	"github.com/hyperledger/fabric/bccsp"
    27  	"github.com/miekg/pkcs11"
    28  	"github.com/stretchr/testify/assert"
    29  )
    30  
    31  func TestKeyGenFailures(t *testing.T) {
    32  	var testOpts bccsp.KeyGenOpts
    33  	ki := currentBCCSP
    34  	_, err := ki.KeyGen(testOpts)
    35  	assert.Error(t, err)
    36  	assert.Contains(t, err.Error(), "Invalid Opts parameter. It must not be nil.")
    37  }
    38  
    39  func TestLoadLib(t *testing.T) {
    40  	// Setup PKCS11 library and provide initial set of values
    41  	lib, pin, label := FindPKCS11Lib()
    42  
    43  	// Test for no specified PKCS11 library
    44  	_, _, _, err := loadLib("", pin, label)
    45  	assert.Error(t, err)
    46  	assert.Contains(t, err.Error(), "No PKCS11 library default")
    47  
    48  	// Test for invalid PKCS11 library
    49  	_, _, _, err = loadLib("badLib", pin, label)
    50  	assert.Error(t, err)
    51  	assert.Contains(t, err.Error(), "Instantiate failed")
    52  
    53  	// Test for invalid label
    54  	_, _, _, err = loadLib(lib, pin, "badLabel")
    55  	assert.Error(t, err)
    56  	assert.Contains(t, err.Error(), "Could not find token with label")
    57  
    58  	// Test for no pin
    59  	_, _, _, err = loadLib(lib, "", label)
    60  	assert.Error(t, err)
    61  	assert.Contains(t, err.Error(), "No PIN set")
    62  }
    63  
    64  func TestOIDFromNamedCurve(t *testing.T) {
    65  	// Test for valid OID for P224
    66  	testOID, boolValue := oidFromNamedCurve(elliptic.P224())
    67  	assert.Equal(t, oidNamedCurveP224, testOID, "Did not receive expected OID for elliptic.P224")
    68  	assert.Equal(t, true, boolValue, "Did not receive a true value when acquiring OID for elliptic.P224")
    69  
    70  	// Test for valid OID for P256
    71  	testOID, boolValue = oidFromNamedCurve(elliptic.P256())
    72  	assert.Equal(t, oidNamedCurveP256, testOID, "Did not receive expected OID for elliptic.P256")
    73  	assert.Equal(t, true, boolValue, "Did not receive a true value when acquiring OID for elliptic.P256")
    74  
    75  	// Test for valid OID for P384
    76  	testOID, boolValue = oidFromNamedCurve(elliptic.P384())
    77  	assert.Equal(t, oidNamedCurveP384, testOID, "Did not receive expected OID for elliptic.P384")
    78  	assert.Equal(t, true, boolValue, "Did not receive a true value when acquiring OID for elliptic.P384")
    79  
    80  	// Test for valid OID for P521
    81  	testOID, boolValue = oidFromNamedCurve(elliptic.P521())
    82  	assert.Equal(t, oidNamedCurveP521, testOID, "Did not receive expected OID for elliptic.P521")
    83  	assert.Equal(t, true, boolValue, "Did not receive a true value when acquiring OID for elliptic.P521")
    84  
    85  	var testCurve elliptic.Curve
    86  	testOID, boolValue = oidFromNamedCurve(testCurve)
    87  	if testOID != nil {
    88  		t.Fatal("Expected nil to be returned.")
    89  	}
    90  }
    91  
    92  func TestNamedCurveFromOID(t *testing.T) {
    93  	// Test for valid P224 elliptic curve
    94  	namedCurve := namedCurveFromOID(oidNamedCurveP224)
    95  	assert.Equal(t, elliptic.P224(), namedCurve, "Did not receive expected named curve for oidNamedCurveP224")
    96  
    97  	// Test for valid P256 elliptic curve
    98  	namedCurve = namedCurveFromOID(oidNamedCurveP256)
    99  	assert.Equal(t, elliptic.P256(), namedCurve, "Did not receive expected named curve for oidNamedCurveP256")
   100  
   101  	// Test for valid P256 elliptic curve
   102  	namedCurve = namedCurveFromOID(oidNamedCurveP384)
   103  	assert.Equal(t, elliptic.P384(), namedCurve, "Did not receive expected named curve for oidNamedCurveP384")
   104  
   105  	// Test for valid P521 elliptic curve
   106  	namedCurve = namedCurveFromOID(oidNamedCurveP521)
   107  	assert.Equal(t, elliptic.P521(), namedCurve, "Did not receive expected named curved for oidNamedCurveP521")
   108  
   109  	testAsn1Value := asn1.ObjectIdentifier{4, 9, 15, 1}
   110  	namedCurve = namedCurveFromOID(testAsn1Value)
   111  	if namedCurve != nil {
   112  		t.Fatal("Expected nil to be returned.")
   113  	}
   114  }
   115  
   116  func TestPKCS11GetSession(t *testing.T) {
   117  	var sessions []pkcs11.SessionHandle
   118  	for i := 0; i < 3*sessionCacheSize; i++ {
   119  		sessions = append(sessions, currentBCCSP.(*impl).getSession())
   120  	}
   121  
   122  	// Return all sessions, should leave sessionCacheSize cached
   123  	for _, session := range sessions {
   124  		currentBCCSP.(*impl).returnSession(session)
   125  	}
   126  	sessions = nil
   127  
   128  	// Lets break OpenSession, so non-cached session cannot be opened
   129  	oldSlot := currentBCCSP.(*impl).slot
   130  	currentBCCSP.(*impl).slot = ^uint(0)
   131  
   132  	// Should be able to get sessionCacheSize cached sessions
   133  	for i := 0; i < sessionCacheSize; i++ {
   134  		sessions = append(sessions, currentBCCSP.(*impl).getSession())
   135  	}
   136  
   137  	// This one should fail
   138  	assert.Panics(t, func() {
   139  		currentBCCSP.(*impl).getSession()
   140  	}, "Should not been able to create another session")
   141  
   142  	// Cleanup
   143  	for _, session := range sessions {
   144  		currentBCCSP.(*impl).returnSession(session)
   145  	}
   146  	currentBCCSP.(*impl).slot = oldSlot
   147  }
   148  
   149  func TestPKCS11ECKeySignVerify(t *testing.T) {
   150  	if currentBCCSP.(*impl).noPrivImport {
   151  		t.Skip("Key import turned off. Skipping Derivation tests as they currently require Key Import.")
   152  	}
   153  
   154  	msg1 := []byte("This is my very authentic message")
   155  	msg2 := []byte("This is my very unauthentic message")
   156  	hash1, _ := currentBCCSP.Hash(msg1, &bccsp.SHAOpts{})
   157  	hash2, _ := currentBCCSP.Hash(msg2, &bccsp.SHAOpts{})
   158  
   159  	var oid asn1.ObjectIdentifier
   160  	if currentTestConfig.securityLevel == 256 {
   161  		oid = oidNamedCurveP256
   162  	} else if currentTestConfig.securityLevel == 384 {
   163  		oid = oidNamedCurveP384
   164  	}
   165  
   166  	key, pubKey, err := currentBCCSP.(*impl).generateECKey(oid, true)
   167  	if err != nil {
   168  		t.Fatalf("Failed generating Key [%s]", err)
   169  	}
   170  
   171  	R, S, err := currentBCCSP.(*impl).signP11ECDSA(key, hash1)
   172  
   173  	if err != nil {
   174  		t.Fatalf("Failed signing message [%s]", err)
   175  	}
   176  
   177  	_, _, err = currentBCCSP.(*impl).signP11ECDSA(nil, hash1)
   178  	assert.Error(t, err)
   179  	assert.Contains(t, err.Error(), "Private key not found")
   180  
   181  	pass, err := currentBCCSP.(*impl).verifyP11ECDSA(key, hash1, R, S, currentTestConfig.securityLevel/8)
   182  	if err != nil {
   183  		t.Fatalf("Error verifying message 1 [%s]", err)
   184  	}
   185  	if pass == false {
   186  		t.Fatal("Signature should match!")
   187  	}
   188  
   189  	pass = ecdsa.Verify(pubKey, hash1, R, S)
   190  	if pass == false {
   191  		t.Fatal("Signature should match with software verification!")
   192  	}
   193  
   194  	pass, err = currentBCCSP.(*impl).verifyP11ECDSA(key, hash2, R, S, currentTestConfig.securityLevel/8)
   195  	if err != nil {
   196  		t.Fatalf("Error verifying message 2 [%s]", err)
   197  	}
   198  
   199  	if pass != false {
   200  		t.Fatal("Signature should not match!")
   201  	}
   202  
   203  	pass = ecdsa.Verify(pubKey, hash2, R, S)
   204  	if pass != false {
   205  		t.Fatal("Signature should not match with software verification!")
   206  	}
   207  }
   208  
   209  func TestPKCS11ECKeyImportSignVerify(t *testing.T) {
   210  	if currentBCCSP.(*impl).noPrivImport {
   211  		t.Skip("Key import turned off. Skipping Derivation tests as they currently require Key Import.")
   212  	}
   213  
   214  	msg1 := []byte("This is my very authentic message")
   215  	msg2 := []byte("This is my very unauthentic message")
   216  	hash1, _ := currentBCCSP.Hash(msg1, &bccsp.SHAOpts{})
   217  	hash2, err := currentBCCSP.Hash(msg2, &bccsp.SHAOpts{})
   218  
   219  	var oid asn1.ObjectIdentifier
   220  	var key *ecdsa.PrivateKey
   221  	if currentTestConfig.securityLevel == 256 {
   222  		oid = oidNamedCurveP256
   223  		key, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   224  		if err != nil {
   225  			t.Fatalf("Failed generating ECDSA key [%s]", err)
   226  		}
   227  	} else if currentTestConfig.securityLevel == 384 {
   228  		oid = oidNamedCurveP384
   229  		key, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
   230  		if err != nil {
   231  			t.Fatalf("Failed generating ECDSA key [%s]", err)
   232  		}
   233  	}
   234  
   235  	ecPt := elliptic.Marshal(key.Curve, key.X, key.Y)
   236  	ski, err := currentBCCSP.(*impl).importECKey(oid, key.D.Bytes(), ecPt, false, privateKeyFlag)
   237  	if err != nil {
   238  		t.Fatalf("Failed getting importing EC Public Key [%s]", err)
   239  	}
   240  
   241  	R, S, err := currentBCCSP.(*impl).signP11ECDSA(ski, hash1)
   242  
   243  	if err != nil {
   244  		t.Fatalf("Failed signing message [%s]", err)
   245  	}
   246  
   247  	pass, err := currentBCCSP.(*impl).verifyP11ECDSA(ski, hash1, R, S, currentTestConfig.securityLevel/8)
   248  	if err != nil {
   249  		t.Fatalf("Error verifying message 1 [%s]\n%s\n\n%s", err, hex.Dump(R.Bytes()), hex.Dump(S.Bytes()))
   250  	}
   251  	if pass == false {
   252  		t.Fatalf("Signature should match!\n%s\n\n%s", hex.Dump(R.Bytes()), hex.Dump(S.Bytes()))
   253  	}
   254  
   255  	pass = ecdsa.Verify(&key.PublicKey, hash1, R, S)
   256  	if pass == false {
   257  		t.Fatal("Signature should match with software verification!")
   258  	}
   259  
   260  	pass, err = currentBCCSP.(*impl).verifyP11ECDSA(ski, hash2, R, S, currentTestConfig.securityLevel/8)
   261  	if err != nil {
   262  		t.Fatalf("Error verifying message 2 [%s]", err)
   263  	}
   264  
   265  	if pass != false {
   266  		t.Fatal("Signature should not match!")
   267  	}
   268  
   269  	pass = ecdsa.Verify(&key.PublicKey, hash2, R, S)
   270  	if pass != false {
   271  		t.Fatal("Signature should not match with software verification!")
   272  	}
   273  }
   274  
   275  func TestPKCS11ECKeyExport(t *testing.T) {
   276  	if currentBCCSP.(*impl).noPrivImport {
   277  		t.Skip("Key import turned off. Skipping Derivation tests as they currently require Key Import.")
   278  	}
   279  
   280  	msg1 := []byte("This is my very authentic message")
   281  	msg2 := []byte("This is my very unauthentic message")
   282  	hash1, _ := currentBCCSP.Hash(msg1, &bccsp.SHAOpts{})
   283  	hash2, err := currentBCCSP.Hash(msg2, &bccsp.SHAOpts{})
   284  
   285  	var oid asn1.ObjectIdentifier
   286  	if currentTestConfig.securityLevel == 256 {
   287  		oid = oidNamedCurveP256
   288  	} else if currentTestConfig.securityLevel == 384 {
   289  		oid = oidNamedCurveP384
   290  	}
   291  
   292  	key, pubKey, err := currentBCCSP.(*impl).generateECKey(oid, false)
   293  	if err != nil {
   294  		t.Fatalf("Failed generating Key [%s]", err)
   295  	}
   296  
   297  	secret := currentBCCSP.(*impl).getSecretValue(key)
   298  	x, y := pubKey.ScalarBaseMult(secret)
   299  
   300  	if 0 != x.Cmp(pubKey.X) {
   301  		t.Fatal("X does not match")
   302  	}
   303  
   304  	if 0 != y.Cmp(pubKey.Y) {
   305  		t.Fatal("Y does not match")
   306  	}
   307  
   308  	ecPt := elliptic.Marshal(pubKey.Curve, x, y)
   309  	key2, err := currentBCCSP.(*impl).importECKey(oid, secret, ecPt, false, privateKeyFlag)
   310  
   311  	R, S, err := currentBCCSP.(*impl).signP11ECDSA(key2, hash1)
   312  	if err != nil {
   313  		t.Fatalf("Failed signing message [%s]", err)
   314  	}
   315  
   316  	pass, err := currentBCCSP.(*impl).verifyP11ECDSA(key2, hash1, R, S, currentTestConfig.securityLevel/8)
   317  	if err != nil {
   318  		t.Fatalf("Error verifying message 1 [%s]", err)
   319  	}
   320  	if pass == false {
   321  		t.Fatal("Signature should match! [1]")
   322  	}
   323  
   324  	pass, err = currentBCCSP.(*impl).verifyP11ECDSA(key, hash1, R, S, currentTestConfig.securityLevel/8)
   325  	if err != nil {
   326  		t.Fatalf("Error verifying message 2 [%s]", err)
   327  	}
   328  	if pass == false {
   329  		t.Fatal("Signature should match! [2]")
   330  	}
   331  
   332  	pass = ecdsa.Verify(pubKey, hash1, R, S)
   333  	if pass == false {
   334  		t.Fatal("Signature should match with software verification!")
   335  	}
   336  
   337  	pass, err = currentBCCSP.(*impl).verifyP11ECDSA(key, hash2, R, S, currentTestConfig.securityLevel/8)
   338  	if err != nil {
   339  		t.Fatalf("Error verifying message 3 [%s]", err)
   340  	}
   341  
   342  	if pass != false {
   343  		t.Fatal("Signature should not match! [3]")
   344  	}
   345  
   346  	pass = ecdsa.Verify(pubKey, hash2, R, S)
   347  	if pass != false {
   348  		t.Fatal("Signature should not match with software verification!")
   349  	}
   350  }