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 }