github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/bccsp/pkcs11/pkcs11.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package pkcs11 8 9 import ( 10 "crypto/ecdsa" 11 "crypto/elliptic" 12 "crypto/sha256" 13 "encoding/asn1" 14 "encoding/hex" 15 "fmt" 16 "math/big" 17 "os" 18 "regexp" 19 "sync" 20 "time" 21 22 "github.com/hechain20/hechain/bccsp" 23 "github.com/hechain20/hechain/bccsp/sw" 24 "github.com/hechain20/hechain/bccsp/utils" 25 "github.com/hechain20/hechain/common/flogging" 26 "github.com/miekg/pkcs11" 27 "github.com/pkg/errors" 28 "go.uber.org/zap/zapcore" 29 ) 30 31 var ( 32 logger = flogging.MustGetLogger("bccsp_p11") 33 invalidSessionRegex = regexp.MustCompile(`.*0xB.:\sCKR.+`) 34 ) 35 36 type Provider struct { 37 bccsp.BCCSP 38 39 slot uint 40 pin string 41 ctx *pkcs11.Ctx 42 curve asn1.ObjectIdentifier 43 softVerify bool 44 immutable bool 45 46 getKeyIDForSKI func(ski []byte) []byte 47 createSessionRetries int 48 createSessionRetryDelay time.Duration 49 50 sessLock sync.Mutex 51 sessPool chan pkcs11.SessionHandle 52 sessions map[pkcs11.SessionHandle]struct{} 53 54 cacheLock sync.RWMutex 55 handleCache map[string]pkcs11.ObjectHandle 56 keyCache map[string]bccsp.Key 57 } 58 59 // Ensure we satisfy the BCCSP interfaces. 60 var _ bccsp.BCCSP = (*Provider)(nil) 61 62 // An Option is used to configure the Provider. 63 type Option func(p *Provider) error 64 65 // WithKeyMapper returns an option that configures the Provider to use the 66 // provided function to map a subject key identifier to a cryptoki CKA_ID 67 // identifer. 68 func WithKeyMapper(mapper func([]byte) []byte) Option { 69 return func(p *Provider) error { 70 p.getKeyIDForSKI = mapper 71 return nil 72 } 73 } 74 75 // New returns a new instance of a BCCSP that uses PKCS#11 standard interfaces 76 // to generate and use elliptic curve key pairs for signing and verification using 77 // curves that satisfy the requested security level from opts. 78 // 79 // All other cryptographic functions are delegated to a software based BCCSP 80 // implementation that is configured to use the security level and hashing 81 // familly from opts and the key store that is provided. 82 func New(opts PKCS11Opts, keyStore bccsp.KeyStore, options ...Option) (*Provider, error) { 83 curve, err := curveForSecurityLevel(opts.Security) 84 if err != nil { 85 return nil, errors.Wrapf(err, "Failed initializing configuration") 86 } 87 88 swCSP, err := sw.NewWithParams(opts.Security, opts.Hash, keyStore) 89 if err != nil { 90 return nil, errors.Wrapf(err, "Failed initializing fallback SW BCCSP") 91 } 92 93 if opts.sessionCacheSize == 0 { 94 opts.sessionCacheSize = defaultSessionCacheSize 95 } 96 if opts.createSessionRetries == 0 { 97 opts.createSessionRetries = defaultCreateSessionRetries 98 } 99 if opts.createSessionRetryDelay == 0 { 100 opts.createSessionRetryDelay = defaultCreateSessionRetryDelay 101 } 102 103 var sessPool chan pkcs11.SessionHandle 104 if opts.sessionCacheSize > 0 { 105 sessPool = make(chan pkcs11.SessionHandle, opts.sessionCacheSize) 106 } 107 108 csp := &Provider{ 109 BCCSP: swCSP, 110 curve: curve, 111 getKeyIDForSKI: func(ski []byte) []byte { return ski }, 112 createSessionRetries: opts.createSessionRetries, 113 createSessionRetryDelay: opts.createSessionRetryDelay, 114 sessPool: sessPool, 115 sessions: map[pkcs11.SessionHandle]struct{}{}, 116 handleCache: map[string]pkcs11.ObjectHandle{}, 117 keyCache: map[string]bccsp.Key{}, 118 softVerify: opts.SoftwareVerify, 119 immutable: opts.Immutable, 120 } 121 122 for _, o := range options { 123 if err := o(csp); err != nil { 124 return nil, err 125 } 126 } 127 128 return csp.initialize(opts) 129 } 130 131 func (csp *Provider) initialize(opts PKCS11Opts) (*Provider, error) { 132 if opts.Library == "" { 133 return nil, fmt.Errorf("pkcs11: library path not provided") 134 } 135 136 ctx := pkcs11.New(opts.Library) 137 if ctx == nil { 138 return nil, fmt.Errorf("pkcs11: instantiation failed for %s", opts.Library) 139 } 140 if err := ctx.Initialize(); err != nil { 141 logger.Debugf("initialize failed: %v", err) 142 } 143 144 slots, err := ctx.GetSlotList(true) 145 if err != nil { 146 return nil, errors.Wrap(err, "pkcs11: get slot list") 147 } 148 for _, s := range slots { 149 info, err := ctx.GetTokenInfo(s) 150 if err != nil || opts.Label != info.Label { 151 continue 152 } 153 154 csp.slot = s 155 csp.ctx = ctx 156 csp.pin = opts.Pin 157 158 session, err := csp.createSession() 159 if err != nil { 160 return nil, err 161 } 162 163 csp.returnSession(session) 164 return csp, nil 165 } 166 167 return nil, errors.Errorf("pkcs11: could not find token with label %s", opts.Label) 168 } 169 170 // KeyGen generates a key using opts. 171 func (csp *Provider) KeyGen(opts bccsp.KeyGenOpts) (k bccsp.Key, err error) { 172 // Validate arguments 173 if opts == nil { 174 return nil, errors.New("Invalid Opts parameter. It must not be nil") 175 } 176 177 // Parse algorithm 178 switch opts.(type) { 179 case *bccsp.ECDSAKeyGenOpts: 180 ski, pub, err := csp.generateECKey(csp.curve, opts.Ephemeral()) 181 if err != nil { 182 return nil, errors.Wrapf(err, "Failed generating ECDSA key") 183 } 184 k = &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, pub}} 185 186 case *bccsp.ECDSAP256KeyGenOpts: 187 ski, pub, err := csp.generateECKey(oidNamedCurveP256, opts.Ephemeral()) 188 if err != nil { 189 return nil, errors.Wrapf(err, "Failed generating ECDSA P256 key") 190 } 191 192 k = &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, pub}} 193 194 case *bccsp.ECDSAP384KeyGenOpts: 195 ski, pub, err := csp.generateECKey(oidNamedCurveP384, opts.Ephemeral()) 196 if err != nil { 197 return nil, errors.Wrapf(err, "Failed generating ECDSA P384 key") 198 } 199 200 k = &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, pub}} 201 202 default: 203 return csp.BCCSP.KeyGen(opts) 204 } 205 206 return k, nil 207 } 208 209 func (csp *Provider) cacheKey(ski []byte, key bccsp.Key) { 210 csp.cacheLock.Lock() 211 csp.keyCache[hex.EncodeToString(ski)] = key 212 csp.cacheLock.Unlock() 213 } 214 215 func (csp *Provider) cachedKey(ski []byte) (bccsp.Key, bool) { 216 csp.cacheLock.RLock() 217 defer csp.cacheLock.RUnlock() 218 key, ok := csp.keyCache[hex.EncodeToString(ski)] 219 return key, ok 220 } 221 222 // GetKey returns the key this CSP associates to 223 // the Subject Key Identifier ski. 224 func (csp *Provider) GetKey(ski []byte) (bccsp.Key, error) { 225 if key, ok := csp.cachedKey(ski); ok { 226 return key, nil 227 } 228 229 pubKey, isPriv, err := csp.getECKey(ski) 230 if err != nil { 231 logger.Debugf("Key not found using PKCS11: %v", err) 232 return csp.BCCSP.GetKey(ski) 233 } 234 235 var key bccsp.Key = &ecdsaPublicKey{ski, pubKey} 236 if isPriv { 237 key = &ecdsaPrivateKey{ski, ecdsaPublicKey{ski, pubKey}} 238 } 239 240 csp.cacheKey(ski, key) 241 return key, nil 242 } 243 244 // Sign signs digest using key k. 245 // The opts argument should be appropriate for the primitive used. 246 // 247 // Note that when a signature of a hash of a larger message is needed, 248 // the caller is responsible for hashing the larger message and passing 249 // the hash (as digest). 250 func (csp *Provider) Sign(k bccsp.Key, digest []byte, opts bccsp.SignerOpts) ([]byte, error) { 251 // Validate arguments 252 if k == nil { 253 return nil, errors.New("Invalid Key. It must not be nil") 254 } 255 if len(digest) == 0 { 256 return nil, errors.New("Invalid digest. Cannot be empty") 257 } 258 259 // Check key type 260 switch key := k.(type) { 261 case *ecdsaPrivateKey: 262 return csp.signECDSA(*key, digest) 263 default: 264 return csp.BCCSP.Sign(key, digest, opts) 265 } 266 } 267 268 func (csp *Provider) signECDSA(k ecdsaPrivateKey, digest []byte) ([]byte, error) { 269 r, s, err := csp.signP11ECDSA(k.ski, digest) 270 if err != nil { 271 return nil, err 272 } 273 274 s, err = utils.ToLowS(k.pub.pub, s) 275 if err != nil { 276 return nil, err 277 } 278 279 return utils.MarshalECDSASignature(r, s) 280 } 281 282 // Verify verifies signature against key k and digest 283 func (csp *Provider) Verify(k bccsp.Key, signature, digest []byte, opts bccsp.SignerOpts) (bool, error) { 284 // Validate arguments 285 if k == nil { 286 return false, errors.New("Invalid Key. It must not be nil") 287 } 288 if len(signature) == 0 { 289 return false, errors.New("Invalid signature. Cannot be empty") 290 } 291 if len(digest) == 0 { 292 return false, errors.New("Invalid digest. Cannot be empty") 293 } 294 295 // key (k) will never be a pkcs11 key, do verify using the software implementation 296 // but validate it just in case 297 switch k.(type) { 298 case *ecdsaPrivateKey, *ecdsaPublicKey: 299 return false, errors.New("Unexpected pkcs11 key, expected software based key") 300 default: 301 return csp.BCCSP.Verify(k, signature, digest, opts) 302 } 303 } 304 305 func (csp *Provider) verifyECDSA(k ecdsaPublicKey, signature, digest []byte) (bool, error) { 306 r, s, err := utils.UnmarshalECDSASignature(signature) 307 if err != nil { 308 return false, fmt.Errorf("Failed unmashalling signature [%s]", err) 309 } 310 311 lowS, err := utils.IsLowS(k.pub, s) 312 if err != nil { 313 return false, err 314 } 315 if !lowS { 316 return false, fmt.Errorf("Invalid S. Must be smaller than half the order [%s][%s]", s, utils.GetCurveHalfOrdersAt(k.pub.Curve)) 317 } 318 319 if csp.softVerify { 320 return ecdsa.Verify(k.pub, digest, r, s), nil 321 } 322 323 return csp.verifyP11ECDSA(k.ski, digest, r, s, k.pub.Curve.Params().BitSize/8) 324 } 325 326 func (csp *Provider) getSession() (session pkcs11.SessionHandle, err error) { 327 for { 328 select { 329 case session = <-csp.sessPool: 330 return 331 default: 332 // cache is empty (or completely in use), create a new session 333 return csp.createSession() 334 } 335 } 336 } 337 338 func (csp *Provider) createSession() (pkcs11.SessionHandle, error) { 339 var sess pkcs11.SessionHandle 340 var err error 341 342 // attempt to open a session with a 100ms delay after each attempt 343 for i := 0; i < csp.createSessionRetries; i++ { 344 sess, err = csp.ctx.OpenSession(csp.slot, pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION) 345 if err == nil { 346 logger.Debugf("Created new pkcs11 session %d on slot %d\n", sess, csp.slot) 347 break 348 } 349 350 logger.Warningf("OpenSession failed, retrying [%s]\n", err) 351 time.Sleep(csp.createSessionRetryDelay) 352 } 353 if err != nil { 354 return 0, errors.Wrap(err, "OpenSession failed") 355 } 356 357 err = csp.ctx.Login(sess, pkcs11.CKU_USER, csp.pin) 358 if err != nil && err != pkcs11.Error(pkcs11.CKR_USER_ALREADY_LOGGED_IN) { 359 csp.ctx.CloseSession(sess) 360 return 0, errors.Wrap(err, "Login failed") 361 } 362 363 csp.sessLock.Lock() 364 csp.sessions[sess] = struct{}{} 365 csp.sessLock.Unlock() 366 367 return sess, nil 368 } 369 370 func (csp *Provider) closeSession(session pkcs11.SessionHandle) { 371 if err := csp.ctx.CloseSession(session); err != nil { 372 logger.Debug("CloseSession failed", err) 373 } 374 375 csp.sessLock.Lock() 376 defer csp.sessLock.Unlock() 377 378 // purge the handle cache if the last session closes 379 delete(csp.sessions, session) 380 if len(csp.sessions) == 0 { 381 csp.clearCaches() 382 } 383 } 384 385 func (csp *Provider) returnSession(session pkcs11.SessionHandle) { 386 select { 387 case csp.sessPool <- session: 388 // returned session back to session cache 389 default: 390 // have plenty of sessions in cache, dropping 391 csp.closeSession(session) 392 } 393 } 394 395 // Look for an EC key by SKI, stored in CKA_ID 396 func (csp *Provider) getECKey(ski []byte) (pubKey *ecdsa.PublicKey, isPriv bool, err error) { 397 session, err := csp.getSession() 398 if err != nil { 399 return nil, false, err 400 } 401 defer func() { csp.handleSessionReturn(err, session) }() 402 403 isPriv = true 404 _, err = csp.findKeyPairFromSKI(session, ski, privateKeyType) 405 if err != nil { 406 isPriv = false 407 logger.Debugf("Private key not found [%s] for SKI [%s], looking for Public key", err, hex.EncodeToString(ski)) 408 } 409 410 publicKey, err := csp.findKeyPairFromSKI(session, ski, publicKeyType) 411 if err != nil { 412 return nil, false, fmt.Errorf("public key not found [%s] for SKI [%s]", err, hex.EncodeToString(ski)) 413 } 414 415 ecpt, marshaledOid, err := csp.ecPoint(session, publicKey) 416 if err != nil { 417 return nil, false, fmt.Errorf("public key not found [%s] for SKI [%s]", err, hex.EncodeToString(ski)) 418 } 419 420 curveOid := new(asn1.ObjectIdentifier) 421 _, err = asn1.Unmarshal(marshaledOid, curveOid) 422 if err != nil { 423 return nil, false, fmt.Errorf("failed Unmarshalling Curve OID [%s]\n%s", err.Error(), hex.EncodeToString(marshaledOid)) 424 } 425 426 curve := namedCurveFromOID(*curveOid) 427 if curve == nil { 428 return nil, false, fmt.Errorf("could not recognize Curve from OID") 429 } 430 x, y := elliptic.Unmarshal(curve, ecpt) 431 if x == nil { 432 return nil, false, fmt.Errorf("failed Unmarshalling Public Key") 433 } 434 435 pubKey = &ecdsa.PublicKey{Curve: curve, X: x, Y: y} 436 return pubKey, isPriv, nil 437 } 438 439 // RFC 5480, 2.1.1.1. Named Curve 440 // 441 // secp224r1 OBJECT IDENTIFIER ::= { 442 // iso(1) identified-organization(3) certicom(132) curve(0) 33 } 443 // 444 // secp256r1 OBJECT IDENTIFIER ::= { 445 // iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) 446 // prime(1) 7 } 447 // 448 // secp384r1 OBJECT IDENTIFIER ::= { 449 // iso(1) identified-organization(3) certicom(132) curve(0) 34 } 450 // 451 // secp521r1 OBJECT IDENTIFIER ::= { 452 // iso(1) identified-organization(3) certicom(132) curve(0) 35 } 453 // 454 var ( 455 oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33} 456 oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} 457 oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34} 458 oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35} 459 ) 460 461 func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve { 462 switch { 463 case oid.Equal(oidNamedCurveP224): 464 return elliptic.P224() 465 case oid.Equal(oidNamedCurveP256): 466 return elliptic.P256() 467 case oid.Equal(oidNamedCurveP384): 468 return elliptic.P384() 469 case oid.Equal(oidNamedCurveP521): 470 return elliptic.P521() 471 } 472 return nil 473 } 474 475 func curveForSecurityLevel(securityLevel int) (asn1.ObjectIdentifier, error) { 476 switch securityLevel { 477 case 256: 478 return oidNamedCurveP256, nil 479 case 384: 480 return oidNamedCurveP384, nil 481 default: 482 return nil, fmt.Errorf("Security level not supported [%d]", securityLevel) 483 } 484 } 485 486 func (csp *Provider) generateECKey(curve asn1.ObjectIdentifier, ephemeral bool) (ski []byte, pubKey *ecdsa.PublicKey, err error) { 487 session, err := csp.getSession() 488 if err != nil { 489 return nil, nil, err 490 } 491 defer func() { csp.handleSessionReturn(err, session) }() 492 493 id := nextIDCtr() 494 publabel := fmt.Sprintf("BCPUB%s", id.Text(16)) 495 prvlabel := fmt.Sprintf("BCPRV%s", id.Text(16)) 496 497 marshaledOID, err := asn1.Marshal(curve) 498 if err != nil { 499 return nil, nil, fmt.Errorf("Could not marshal OID [%s]", err.Error()) 500 } 501 502 pubkeyT := []*pkcs11.Attribute{ 503 pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC), 504 pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY), 505 pkcs11.NewAttribute(pkcs11.CKA_TOKEN, !ephemeral), 506 pkcs11.NewAttribute(pkcs11.CKA_VERIFY, true), 507 pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, marshaledOID), 508 509 pkcs11.NewAttribute(pkcs11.CKA_ID, publabel), 510 pkcs11.NewAttribute(pkcs11.CKA_LABEL, publabel), 511 } 512 513 prvkeyT := []*pkcs11.Attribute{ 514 pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC), 515 pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY), 516 pkcs11.NewAttribute(pkcs11.CKA_TOKEN, !ephemeral), 517 pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, true), 518 pkcs11.NewAttribute(pkcs11.CKA_SIGN, true), 519 520 pkcs11.NewAttribute(pkcs11.CKA_ID, prvlabel), 521 pkcs11.NewAttribute(pkcs11.CKA_LABEL, prvlabel), 522 523 pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, false), 524 pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true), 525 } 526 527 pub, prv, err := csp.ctx.GenerateKeyPair(session, 528 []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_EC_KEY_PAIR_GEN, nil)}, 529 pubkeyT, 530 prvkeyT, 531 ) 532 if err != nil { 533 return nil, nil, fmt.Errorf("P11: keypair generate failed [%s]", err) 534 } 535 536 ecpt, _, err := csp.ecPoint(session, pub) 537 if err != nil { 538 return nil, nil, fmt.Errorf("Error querying EC-point: [%s]", err) 539 } 540 hash := sha256.Sum256(ecpt) 541 ski = hash[:] 542 543 // set CKA_ID of the both keys to SKI(public key) and CKA_LABEL to hex string of SKI 544 setskiT := []*pkcs11.Attribute{ 545 pkcs11.NewAttribute(pkcs11.CKA_ID, ski), 546 pkcs11.NewAttribute(pkcs11.CKA_LABEL, hex.EncodeToString(ski)), 547 } 548 549 logger.Infof("Generated new P11 key, SKI %x\n", ski) 550 err = csp.ctx.SetAttributeValue(session, pub, setskiT) 551 if err != nil { 552 return nil, nil, fmt.Errorf("P11: set-ID-to-SKI[public] failed [%s]", err) 553 } 554 555 err = csp.ctx.SetAttributeValue(session, prv, setskiT) 556 if err != nil { 557 return nil, nil, fmt.Errorf("P11: set-ID-to-SKI[private] failed [%s]", err) 558 } 559 560 // Set CKA_Modifible to false for both public key and private keys 561 if csp.immutable { 562 setCKAModifiable := []*pkcs11.Attribute{ 563 pkcs11.NewAttribute(pkcs11.CKA_MODIFIABLE, false), 564 } 565 566 _, pubCopyerror := csp.ctx.CopyObject(session, pub, setCKAModifiable) 567 if pubCopyerror != nil { 568 return nil, nil, fmt.Errorf("P11: Public Key copy failed with error [%s] . Please contact your HSM vendor", pubCopyerror) 569 } 570 571 pubKeyDestroyError := csp.ctx.DestroyObject(session, pub) 572 if pubKeyDestroyError != nil { 573 return nil, nil, fmt.Errorf("P11: Public Key destroy failed with error [%s]. Please contact your HSM vendor", pubCopyerror) 574 } 575 576 _, prvCopyerror := csp.ctx.CopyObject(session, prv, setCKAModifiable) 577 if prvCopyerror != nil { 578 return nil, nil, fmt.Errorf("P11: Private Key copy failed with error [%s]. Please contact your HSM vendor", prvCopyerror) 579 } 580 prvKeyDestroyError := csp.ctx.DestroyObject(session, prv) 581 if prvKeyDestroyError != nil { 582 return nil, nil, fmt.Errorf("P11: Private Key destroy failed with error [%s]. Please contact your HSM vendor", prvKeyDestroyError) 583 } 584 } 585 586 nistCurve := namedCurveFromOID(curve) 587 if curve == nil { 588 return nil, nil, fmt.Errorf("Cound not recognize Curve from OID") 589 } 590 x, y := elliptic.Unmarshal(nistCurve, ecpt) 591 if x == nil { 592 return nil, nil, fmt.Errorf("Failed Unmarshalling Public Key") 593 } 594 595 pubGoKey := &ecdsa.PublicKey{Curve: nistCurve, X: x, Y: y} 596 597 if logger.IsEnabledFor(zapcore.DebugLevel) { 598 listAttrs(csp.ctx, session, prv) 599 listAttrs(csp.ctx, session, pub) 600 } 601 602 return ski, pubGoKey, nil 603 } 604 605 func (csp *Provider) signP11ECDSA(ski []byte, msg []byte) (R, S *big.Int, err error) { 606 session, err := csp.getSession() 607 if err != nil { 608 return nil, nil, err 609 } 610 defer func() { csp.handleSessionReturn(err, session) }() 611 612 privateKey, err := csp.findKeyPairFromSKI(session, ski, privateKeyType) 613 if err != nil { 614 return nil, nil, fmt.Errorf("Private key not found [%s]", err) 615 } 616 617 err = csp.ctx.SignInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_ECDSA, nil)}, privateKey) 618 if err != nil { 619 return nil, nil, fmt.Errorf("Sign-initialize failed [%s]", err) 620 } 621 622 var sig []byte 623 624 sig, err = csp.ctx.Sign(session, msg) 625 if err != nil { 626 return nil, nil, fmt.Errorf("P11: sign failed [%s]", err) 627 } 628 629 R = new(big.Int) 630 S = new(big.Int) 631 R.SetBytes(sig[0 : len(sig)/2]) 632 S.SetBytes(sig[len(sig)/2:]) 633 634 return R, S, nil 635 } 636 637 func (csp *Provider) verifyP11ECDSA(ski []byte, msg []byte, R, S *big.Int, byteSize int) (bool, error) { 638 session, err := csp.getSession() 639 if err != nil { 640 return false, err 641 } 642 defer func() { csp.handleSessionReturn(err, session) }() 643 644 logger.Debugf("Verify ECDSA") 645 646 publicKey, err := csp.findKeyPairFromSKI(session, ski, publicKeyType) 647 if err != nil { 648 return false, fmt.Errorf("Public key not found [%s]", err) 649 } 650 651 r := R.Bytes() 652 s := S.Bytes() 653 654 // Pad front of R and S with Zeroes if needed 655 sig := make([]byte, 2*byteSize) 656 copy(sig[byteSize-len(r):byteSize], r) 657 copy(sig[2*byteSize-len(s):], s) 658 659 err = csp.ctx.VerifyInit( 660 session, 661 []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_ECDSA, nil)}, 662 publicKey, 663 ) 664 if err != nil { 665 return false, fmt.Errorf("PKCS11: Verify-initialize [%s]", err) 666 } 667 err = csp.ctx.Verify(session, msg, sig) 668 if err == pkcs11.Error(pkcs11.CKR_SIGNATURE_INVALID) { 669 return false, nil 670 } 671 if err != nil { 672 return false, fmt.Errorf("PKCS11: Verify failed [%s]", err) 673 } 674 675 return true, nil 676 } 677 678 type keyType int8 679 680 const ( 681 publicKeyType keyType = iota 682 privateKeyType 683 ) 684 685 func (csp *Provider) cachedHandle(keyType keyType, ski []byte) (pkcs11.ObjectHandle, bool) { 686 cacheKey := hex.EncodeToString(append([]byte{byte(keyType)}, ski...)) 687 csp.cacheLock.RLock() 688 defer csp.cacheLock.RUnlock() 689 690 handle, ok := csp.handleCache[cacheKey] 691 return handle, ok 692 } 693 694 func (csp *Provider) cacheHandle(keyType keyType, ski []byte, handle pkcs11.ObjectHandle) { 695 cacheKey := hex.EncodeToString(append([]byte{byte(keyType)}, ski...)) 696 csp.cacheLock.Lock() 697 defer csp.cacheLock.Unlock() 698 699 csp.handleCache[cacheKey] = handle 700 } 701 702 func (csp *Provider) clearCaches() { 703 csp.cacheLock.Lock() 704 defer csp.cacheLock.Unlock() 705 csp.handleCache = map[string]pkcs11.ObjectHandle{} 706 csp.keyCache = map[string]bccsp.Key{} 707 } 708 709 func (csp *Provider) findKeyPairFromSKI(session pkcs11.SessionHandle, ski []byte, keyType keyType) (pkcs11.ObjectHandle, error) { 710 // check for cached handle 711 if handle, ok := csp.cachedHandle(keyType, ski); ok { 712 return handle, nil 713 } 714 715 ktype := pkcs11.CKO_PUBLIC_KEY 716 if keyType == privateKeyType { 717 ktype = pkcs11.CKO_PRIVATE_KEY 718 } 719 720 template := []*pkcs11.Attribute{ 721 pkcs11.NewAttribute(pkcs11.CKA_CLASS, ktype), 722 pkcs11.NewAttribute(pkcs11.CKA_ID, csp.getKeyIDForSKI(ski)), 723 } 724 if err := csp.ctx.FindObjectsInit(session, template); err != nil { 725 return 0, err 726 } 727 defer csp.ctx.FindObjectsFinal(session) 728 729 // single session instance, assume one hit only 730 objs, _, err := csp.ctx.FindObjects(session, 1) 731 if err != nil { 732 return 0, err 733 } 734 735 if len(objs) == 0 { 736 return 0, fmt.Errorf("Key not found [%s]", hex.Dump(ski)) 737 } 738 739 // cache the found handle 740 csp.cacheHandle(keyType, ski, objs[0]) 741 742 return objs[0], nil 743 } 744 745 // Fairly straightforward EC-point query, other than opencryptoki 746 // mis-reporting length, including the 04 Tag of the field following 747 // the SPKI in EP11-returned MACed publickeys: 748 // 749 // attr type 385/x181, length 66 b -- SHOULD be 1+64 750 // EC point: 751 // 00000000 04 ce 30 31 6d 5a fd d3 53 2d 54 9a 27 54 d8 7c 752 // 00000010 d9 80 35 91 09 2d 6f 06 5a 8e e3 cb c0 01 b7 c9 753 // 00000020 13 5d 70 d4 e5 62 f2 1b 10 93 f7 d5 77 41 ba 9d 754 // 00000030 93 3e 18 3e 00 c6 0a 0e d2 36 cc 7f be 50 16 ef 755 // 00000040 06 04 756 // 757 // cf. correct field: 758 // 0 89: SEQUENCE { 759 // 2 19: SEQUENCE { 760 // 4 7: OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) 761 // 13 8: OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) 762 // : } 763 // 23 66: BIT STRING 764 // : 04 CE 30 31 6D 5A FD D3 53 2D 54 9A 27 54 D8 7C 765 // : D9 80 35 91 09 2D 6F 06 5A 8E E3 CB C0 01 B7 C9 766 // : 13 5D 70 D4 E5 62 F2 1B 10 93 F7 D5 77 41 BA 9D 767 // : 93 3E 18 3E 00 C6 0A 0E D2 36 CC 7F BE 50 16 EF 768 // : 06 769 // : } 770 // 771 // as a short-term workaround, remove the trailing byte if: 772 // - receiving an even number of bytes == 2*prime-coordinate +2 bytes 773 // - starting byte is 04: uncompressed EC point 774 // - trailing byte is 04: assume it belongs to the next OCTET STRING 775 // 776 // [mis-parsing encountered with v3.5.1, 2016-10-22] 777 // 778 // SoftHSM reports extra two bytes before the uncompressed point 779 // 0x04 || <Length*2+1> 780 // VV< Actual start of point 781 // 00000000 04 41 04 6c c8 57 32 13 02 12 6a 19 23 1d 5a 64 |.A.l.W2...j.#.Zd| 782 // 00000010 33 0c eb 75 4d e8 99 22 92 35 96 b2 39 58 14 1e |3..uM..".5..9X..| 783 // 00000020 19 de ef 32 46 50 68 02 24 62 36 db ed b1 84 7b |...2FPh.$b6....{| 784 // 00000030 93 d8 40 c3 d5 a6 b7 38 16 d2 35 0a 53 11 f9 51 |..@....8..5.S..Q| 785 // 00000040 fc a7 16 |...| 786 func (csp *Provider) ecPoint(session pkcs11.SessionHandle, key pkcs11.ObjectHandle) (ecpt, oid []byte, err error) { 787 template := []*pkcs11.Attribute{ 788 pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, nil), 789 pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, nil), 790 } 791 792 attr, err := csp.ctx.GetAttributeValue(session, key, template) 793 if err != nil { 794 return nil, nil, fmt.Errorf("PKCS11: get(EC point) [%s]", err) 795 } 796 797 for _, a := range attr { 798 if a.Type == pkcs11.CKA_EC_POINT { 799 logger.Debugf("EC point: attr type %d/0x%x, len %d\n%s\n", a.Type, a.Type, len(a.Value), hex.Dump(a.Value)) 800 801 // workarounds, see above 802 if ((len(a.Value) % 2) == 0) && 803 (byte(0x04) == a.Value[0]) && 804 (byte(0x04) == a.Value[len(a.Value)-1]) { 805 logger.Debugf("Detected opencryptoki bug, trimming trailing 0x04") 806 ecpt = a.Value[0 : len(a.Value)-1] // Trim trailing 0x04 807 } else if byte(0x04) == a.Value[0] && byte(0x04) == a.Value[2] { 808 logger.Debugf("Detected SoftHSM bug, trimming leading 0x04 0xXX") 809 ecpt = a.Value[2:len(a.Value)] 810 } else { 811 ecpt = a.Value 812 } 813 } else if a.Type == pkcs11.CKA_EC_PARAMS { 814 logger.Debugf("EC point: attr type %d/0x%x, len %d\n%s\n", a.Type, a.Type, len(a.Value), hex.Dump(a.Value)) 815 816 oid = a.Value 817 } 818 } 819 if oid == nil || ecpt == nil { 820 return nil, nil, fmt.Errorf("CKA_EC_POINT not found, perhaps not an EC Key?") 821 } 822 823 return ecpt, oid, nil 824 } 825 826 func (csp *Provider) handleSessionReturn(err error, session pkcs11.SessionHandle) { 827 if err != nil { 828 if invalidSessionRegex.MatchString(err.Error()) { 829 logger.Infof("PKCS11 session invalidated, closing session: %v", err) 830 csp.closeSession(session) 831 return 832 } 833 } 834 csp.returnSession(session) 835 } 836 837 func listAttrs(p11lib *pkcs11.Ctx, session pkcs11.SessionHandle, obj pkcs11.ObjectHandle) { 838 var cktype, ckclass uint 839 var ckaid, cklabel []byte 840 841 if p11lib == nil { 842 return 843 } 844 845 template := []*pkcs11.Attribute{ 846 pkcs11.NewAttribute(pkcs11.CKA_CLASS, ckclass), 847 pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, cktype), 848 pkcs11.NewAttribute(pkcs11.CKA_ID, ckaid), 849 pkcs11.NewAttribute(pkcs11.CKA_LABEL, cklabel), 850 } 851 852 // certain errors are tolerated, if value is missing 853 attr, err := p11lib.GetAttributeValue(session, obj, template) 854 if err != nil { 855 logger.Debugf("P11: get(attrlist) [%s]\n", err) 856 } 857 858 for _, a := range attr { 859 // Would be friendlier if the bindings provided a way convert Attribute hex to string 860 logger.Debugf("ListAttr: type %d/0x%x, length %d\n%s", a.Type, a.Type, len(a.Value), hex.Dump(a.Value)) 861 } 862 } 863 864 var ( 865 bigone = new(big.Int).SetInt64(1) 866 idCtr = new(big.Int) 867 idMutex sync.Mutex 868 ) 869 870 func nextIDCtr() *big.Int { 871 idMutex.Lock() 872 idCtr = new(big.Int).Add(idCtr, bigone) 873 idMutex.Unlock() 874 return idCtr 875 } 876 877 // FindPKCS11Lib IS ONLY USED FOR TESTING 878 // This is a convenience function. Useful to self-configure, for tests where 879 // usual configuration is not available. 880 func FindPKCS11Lib() (lib, pin, label string) { 881 if lib = os.Getenv("PKCS11_LIB"); lib == "" { 882 possibilities := []string{ 883 "/usr/lib/softhsm/libsofthsm2.so", // Debian 884 "/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so", // Ubuntu 885 } 886 for _, path := range possibilities { 887 if _, err := os.Stat(path); !os.IsNotExist(err) { 888 lib = path 889 break 890 } 891 } 892 } 893 if pin = os.Getenv("PKCS11_PIN"); pin == "" { 894 pin = "98765432" 895 } 896 if label = os.Getenv("PKCS11_LABEL"); label == "" { 897 label = "ForFabric" 898 } 899 900 return lib, pin, label 901 }