github.com/true-sqn/fabric@v2.1.1+incompatible/bccsp/pkcs11/pkcs11.go (about) 1 /* 2 Copyright IBM Corp. 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 "sync" 18 "time" 19 20 "github.com/miekg/pkcs11" 21 "go.uber.org/zap/zapcore" 22 ) 23 24 func loadLib(lib, pin, label string) (*pkcs11.Ctx, uint, *pkcs11.SessionHandle, error) { 25 var slot uint 26 logger.Debugf("Loading pkcs11 library [%s]\n", lib) 27 if lib == "" { 28 return nil, slot, nil, fmt.Errorf("No PKCS11 library default") 29 } 30 31 ctx := pkcs11.New(lib) 32 if ctx == nil { 33 return nil, slot, nil, fmt.Errorf("Instantiate failed [%s]", lib) 34 } 35 36 ctx.Initialize() 37 slots, err := ctx.GetSlotList(true) 38 if err != nil { 39 return nil, slot, nil, fmt.Errorf("Could not get Slot List [%s]", err) 40 } 41 found := false 42 for _, s := range slots { 43 info, errToken := ctx.GetTokenInfo(s) 44 if errToken != nil { 45 continue 46 } 47 logger.Debugf("Looking for %s, found label %s\n", label, info.Label) 48 if label == info.Label { 49 found = true 50 slot = s 51 break 52 } 53 } 54 if !found { 55 return nil, slot, nil, fmt.Errorf("Could not find token with label %s", label) 56 } 57 58 session := createSession(ctx, slot, pin) 59 60 logger.Debugf("Created new pkcs11 session %+v on slot %d\n", session, slot) 61 62 if pin == "" { 63 return nil, slot, nil, fmt.Errorf("No PIN set") 64 } 65 err = ctx.Login(session, pkcs11.CKU_USER, pin) 66 if err != nil { 67 if err != pkcs11.Error(pkcs11.CKR_USER_ALREADY_LOGGED_IN) { 68 return nil, slot, nil, fmt.Errorf("Login failed [%s]", err) 69 } 70 } 71 72 return ctx, slot, &session, nil 73 } 74 75 func (csp *impl) getSession() (session pkcs11.SessionHandle) { 76 select { 77 case session = <-csp.sessions: 78 _, err := csp.ctx.GetSessionInfo(session) 79 if err != nil { 80 logger.Warningf("Get session info failed [%s], closing existing session and getting a new session\n", err) 81 csp.ctx.CloseSession(session) 82 session = createSession(csp.ctx, csp.slot, csp.pin) 83 } else { 84 logger.Debugf("Reusing existing pkcs11 session %+v on slot %d\n", session, csp.slot) 85 } 86 87 default: 88 // cache is empty (or completely in use), create a new session 89 session = createSession(csp.ctx, csp.slot, csp.pin) 90 } 91 return session 92 } 93 94 func createSession(ctx *pkcs11.Ctx, slot uint, pin string) pkcs11.SessionHandle { 95 var s pkcs11.SessionHandle 96 var err error 97 // attempt 10 times to open a session with a 100ms delay after each attempt 98 for i := 0; i < 10; i++ { 99 s, err = ctx.OpenSession(slot, pkcs11.CKF_SERIAL_SESSION|pkcs11.CKF_RW_SESSION) 100 if err != nil { 101 logger.Warningf("OpenSession failed, retrying [%s]\n", err) 102 } else { 103 break 104 } 105 time.Sleep(100 * time.Millisecond) 106 } 107 if err != nil { 108 logger.Fatalf("OpenSession failed [%s]", err) 109 } 110 logger.Debugf("Created new pkcs11 session %+v on slot %d\n", s, slot) 111 session := s 112 113 err = ctx.Login(session, pkcs11.CKU_USER, pin) 114 if err != nil { 115 if err != pkcs11.Error(pkcs11.CKR_USER_ALREADY_LOGGED_IN) { 116 logger.Errorf("Login failed [%s]", err) 117 } 118 } 119 return session 120 } 121 122 func (csp *impl) returnSession(session pkcs11.SessionHandle) { 123 select { 124 case csp.sessions <- session: 125 // returned session back to session cache 126 default: 127 // have plenty of sessions in cache, dropping 128 csp.ctx.CloseSession(session) 129 } 130 } 131 132 // Look for an EC key by SKI, stored in CKA_ID 133 func (csp *impl) getECKey(ski []byte) (pubKey *ecdsa.PublicKey, isPriv bool, err error) { 134 p11lib := csp.ctx 135 session := csp.getSession() 136 defer csp.returnSession(session) 137 isPriv = true 138 _, err = findKeyPairFromSKI(p11lib, session, ski, privateKeyType) 139 if err != nil { 140 isPriv = false 141 logger.Debugf("Private key not found [%s] for SKI [%s], looking for Public key", err, hex.EncodeToString(ski)) 142 } 143 144 publicKey, err := findKeyPairFromSKI(p11lib, session, ski, publicKeyType) 145 if err != nil { 146 return nil, false, fmt.Errorf("Public key not found [%s] for SKI [%s]", err, hex.EncodeToString(ski)) 147 } 148 149 ecpt, marshaledOid, err := ecPoint(p11lib, session, *publicKey) 150 if err != nil { 151 return nil, false, fmt.Errorf("Public key not found [%s] for SKI [%s]", err, hex.EncodeToString(ski)) 152 } 153 154 curveOid := new(asn1.ObjectIdentifier) 155 _, err = asn1.Unmarshal(marshaledOid, curveOid) 156 if err != nil { 157 return nil, false, fmt.Errorf("Failed Unmarshaling Curve OID [%s]\n%s", err.Error(), hex.EncodeToString(marshaledOid)) 158 } 159 160 curve := namedCurveFromOID(*curveOid) 161 if curve == nil { 162 return nil, false, fmt.Errorf("Cound not recognize Curve from OID") 163 } 164 x, y := elliptic.Unmarshal(curve, ecpt) 165 if x == nil { 166 return nil, false, fmt.Errorf("Failed Unmarshaling Public Key") 167 } 168 169 pubKey = &ecdsa.PublicKey{Curve: curve, X: x, Y: y} 170 return pubKey, isPriv, nil 171 } 172 173 // RFC 5480, 2.1.1.1. Named Curve 174 // 175 // secp224r1 OBJECT IDENTIFIER ::= { 176 // iso(1) identified-organization(3) certicom(132) curve(0) 33 } 177 // 178 // secp256r1 OBJECT IDENTIFIER ::= { 179 // iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) 180 // prime(1) 7 } 181 // 182 // secp384r1 OBJECT IDENTIFIER ::= { 183 // iso(1) identified-organization(3) certicom(132) curve(0) 34 } 184 // 185 // secp521r1 OBJECT IDENTIFIER ::= { 186 // iso(1) identified-organization(3) certicom(132) curve(0) 35 } 187 // 188 var ( 189 oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33} 190 oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} 191 oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34} 192 oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35} 193 ) 194 195 func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve { 196 switch { 197 case oid.Equal(oidNamedCurveP224): 198 return elliptic.P224() 199 case oid.Equal(oidNamedCurveP256): 200 return elliptic.P256() 201 case oid.Equal(oidNamedCurveP384): 202 return elliptic.P384() 203 case oid.Equal(oidNamedCurveP521): 204 return elliptic.P521() 205 } 206 return nil 207 } 208 209 func (csp *impl) generateECKey(curve asn1.ObjectIdentifier, ephemeral bool) (ski []byte, pubKey *ecdsa.PublicKey, err error) { 210 p11lib := csp.ctx 211 session := csp.getSession() 212 defer csp.returnSession(session) 213 214 id := nextIDCtr() 215 publabel := fmt.Sprintf("BCPUB%s", id.Text(16)) 216 prvlabel := fmt.Sprintf("BCPRV%s", id.Text(16)) 217 218 marshaledOID, err := asn1.Marshal(curve) 219 if err != nil { 220 return nil, nil, fmt.Errorf("Could not marshal OID [%s]", err.Error()) 221 } 222 223 pubkeyT := []*pkcs11.Attribute{ 224 pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC), 225 pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PUBLIC_KEY), 226 pkcs11.NewAttribute(pkcs11.CKA_TOKEN, !ephemeral), 227 pkcs11.NewAttribute(pkcs11.CKA_VERIFY, true), 228 pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, marshaledOID), 229 230 pkcs11.NewAttribute(pkcs11.CKA_ID, publabel), 231 pkcs11.NewAttribute(pkcs11.CKA_LABEL, publabel), 232 } 233 234 prvkeyT := []*pkcs11.Attribute{ 235 pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_EC), 236 pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY), 237 pkcs11.NewAttribute(pkcs11.CKA_TOKEN, !ephemeral), 238 pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, true), 239 pkcs11.NewAttribute(pkcs11.CKA_SIGN, true), 240 241 pkcs11.NewAttribute(pkcs11.CKA_ID, prvlabel), 242 pkcs11.NewAttribute(pkcs11.CKA_LABEL, prvlabel), 243 244 pkcs11.NewAttribute(pkcs11.CKA_EXTRACTABLE, false), 245 pkcs11.NewAttribute(pkcs11.CKA_SENSITIVE, true), 246 } 247 248 pub, prv, err := p11lib.GenerateKeyPair(session, 249 []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_EC_KEY_PAIR_GEN, nil)}, 250 pubkeyT, prvkeyT) 251 252 if err != nil { 253 return nil, nil, fmt.Errorf("P11: keypair generate failed [%s]", err) 254 } 255 256 ecpt, _, err := ecPoint(p11lib, session, pub) 257 if err != nil { 258 return nil, nil, fmt.Errorf("Error querying EC-point: [%s]", err) 259 } 260 hash := sha256.Sum256(ecpt) 261 ski = hash[:] 262 263 // set CKA_ID of the both keys to SKI(public key) and CKA_LABEL to hex string of SKI 264 setskiT := []*pkcs11.Attribute{ 265 pkcs11.NewAttribute(pkcs11.CKA_ID, ski), 266 pkcs11.NewAttribute(pkcs11.CKA_LABEL, hex.EncodeToString(ski)), 267 } 268 269 logger.Infof("Generated new P11 key, SKI %x\n", ski) 270 err = p11lib.SetAttributeValue(session, pub, setskiT) 271 if err != nil { 272 return nil, nil, fmt.Errorf("P11: set-ID-to-SKI[public] failed [%s]", err) 273 } 274 275 err = p11lib.SetAttributeValue(session, prv, setskiT) 276 if err != nil { 277 return nil, nil, fmt.Errorf("P11: set-ID-to-SKI[private] failed [%s]", err) 278 } 279 280 //Set CKA_Modifible to false for both public key and private keys 281 if csp.immutable { 282 setCKAModifiable := []*pkcs11.Attribute{ 283 pkcs11.NewAttribute(pkcs11.CKA_MODIFIABLE, false), 284 } 285 286 _, pubCopyerror := p11lib.CopyObject(session, pub, setCKAModifiable) 287 if pubCopyerror != nil { 288 return nil, nil, fmt.Errorf("P11: Public Key copy failed with error [%s] . Please contact your HSM vendor", pubCopyerror) 289 } 290 291 pubKeyDestroyError := p11lib.DestroyObject(session, pub) 292 if pubKeyDestroyError != nil { 293 return nil, nil, fmt.Errorf("P11: Public Key destroy failed with error [%s]. Please contact your HSM vendor", pubCopyerror) 294 } 295 296 _, prvCopyerror := p11lib.CopyObject(session, prv, setCKAModifiable) 297 if prvCopyerror != nil { 298 return nil, nil, fmt.Errorf("P11: Private Key copy failed with error [%s]. Please contact your HSM vendor", prvCopyerror) 299 } 300 prvKeyDestroyError := p11lib.DestroyObject(session, prv) 301 if pubKeyDestroyError != nil { 302 return nil, nil, fmt.Errorf("P11: Private Key destroy failed with error [%s]. Please contact your HSM vendor", prvKeyDestroyError) 303 } 304 } 305 306 nistCurve := namedCurveFromOID(curve) 307 if curve == nil { 308 return nil, nil, fmt.Errorf("Cound not recognize Curve from OID") 309 } 310 x, y := elliptic.Unmarshal(nistCurve, ecpt) 311 if x == nil { 312 return nil, nil, fmt.Errorf("Failed Unmarshaling Public Key") 313 } 314 315 pubGoKey := &ecdsa.PublicKey{Curve: nistCurve, X: x, Y: y} 316 317 if logger.IsEnabledFor(zapcore.DebugLevel) { 318 listAttrs(p11lib, session, prv) 319 listAttrs(p11lib, session, pub) 320 } 321 322 return ski, pubGoKey, nil 323 } 324 325 func (csp *impl) signP11ECDSA(ski []byte, msg []byte) (R, S *big.Int, err error) { 326 p11lib := csp.ctx 327 session := csp.getSession() 328 defer csp.returnSession(session) 329 330 privateKey, err := findKeyPairFromSKI(p11lib, session, ski, privateKeyType) 331 if err != nil { 332 return nil, nil, fmt.Errorf("Private key not found [%s]", err) 333 } 334 335 err = p11lib.SignInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_ECDSA, nil)}, *privateKey) 336 if err != nil { 337 return nil, nil, fmt.Errorf("Sign-initialize failed [%s]", err) 338 } 339 340 var sig []byte 341 342 sig, err = p11lib.Sign(session, msg) 343 if err != nil { 344 return nil, nil, fmt.Errorf("P11: sign failed [%s]", err) 345 } 346 347 R = new(big.Int) 348 S = new(big.Int) 349 R.SetBytes(sig[0 : len(sig)/2]) 350 S.SetBytes(sig[len(sig)/2:]) 351 352 return R, S, nil 353 } 354 355 func (csp *impl) verifyP11ECDSA(ski []byte, msg []byte, R, S *big.Int, byteSize int) (bool, error) { 356 p11lib := csp.ctx 357 session := csp.getSession() 358 defer csp.returnSession(session) 359 360 logger.Debugf("Verify ECDSA\n") 361 362 publicKey, err := findKeyPairFromSKI(p11lib, session, ski, publicKeyType) 363 if err != nil { 364 return false, fmt.Errorf("Public key not found [%s]", err) 365 } 366 367 r := R.Bytes() 368 s := S.Bytes() 369 370 // Pad front of R and S with Zeroes if needed 371 sig := make([]byte, 2*byteSize) 372 copy(sig[byteSize-len(r):byteSize], r) 373 copy(sig[2*byteSize-len(s):], s) 374 375 err = p11lib.VerifyInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_ECDSA, nil)}, 376 *publicKey) 377 if err != nil { 378 return false, fmt.Errorf("PKCS11: Verify-initialize [%s]", err) 379 } 380 err = p11lib.Verify(session, msg, sig) 381 if err == pkcs11.Error(pkcs11.CKR_SIGNATURE_INVALID) { 382 return false, nil 383 } 384 if err != nil { 385 return false, fmt.Errorf("PKCS11: Verify failed [%s]", err) 386 } 387 388 return true, nil 389 } 390 391 type keyType int8 392 393 const ( 394 publicKeyType keyType = iota 395 privateKeyType 396 ) 397 398 func findKeyPairFromSKI(mod *pkcs11.Ctx, session pkcs11.SessionHandle, ski []byte, keyType keyType) (*pkcs11.ObjectHandle, error) { 399 ktype := pkcs11.CKO_PUBLIC_KEY 400 if keyType == privateKeyType { 401 ktype = pkcs11.CKO_PRIVATE_KEY 402 } 403 404 template := []*pkcs11.Attribute{ 405 pkcs11.NewAttribute(pkcs11.CKA_CLASS, ktype), 406 pkcs11.NewAttribute(pkcs11.CKA_ID, ski), 407 } 408 if err := mod.FindObjectsInit(session, template); err != nil { 409 return nil, err 410 } 411 412 // single session instance, assume one hit only 413 objs, _, err := mod.FindObjects(session, 1) 414 if err != nil { 415 return nil, err 416 } 417 if err = mod.FindObjectsFinal(session); err != nil { 418 return nil, err 419 } 420 421 if len(objs) == 0 { 422 return nil, fmt.Errorf("Key not found [%s]", hex.Dump(ski)) 423 } 424 425 return &objs[0], nil 426 } 427 428 // Fairly straightforward EC-point query, other than opencryptoki 429 // mis-reporting length, including the 04 Tag of the field following 430 // the SPKI in EP11-returned MACed publickeys: 431 // 432 // attr type 385/x181, length 66 b -- SHOULD be 1+64 433 // EC point: 434 // 00000000 04 ce 30 31 6d 5a fd d3 53 2d 54 9a 27 54 d8 7c 435 // 00000010 d9 80 35 91 09 2d 6f 06 5a 8e e3 cb c0 01 b7 c9 436 // 00000020 13 5d 70 d4 e5 62 f2 1b 10 93 f7 d5 77 41 ba 9d 437 // 00000030 93 3e 18 3e 00 c6 0a 0e d2 36 cc 7f be 50 16 ef 438 // 00000040 06 04 439 // 440 // cf. correct field: 441 // 0 89: SEQUENCE { 442 // 2 19: SEQUENCE { 443 // 4 7: OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) 444 // 13 8: OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) 445 // : } 446 // 23 66: BIT STRING 447 // : 04 CE 30 31 6D 5A FD D3 53 2D 54 9A 27 54 D8 7C 448 // : D9 80 35 91 09 2D 6F 06 5A 8E E3 CB C0 01 B7 C9 449 // : 13 5D 70 D4 E5 62 F2 1B 10 93 F7 D5 77 41 BA 9D 450 // : 93 3E 18 3E 00 C6 0A 0E D2 36 CC 7F BE 50 16 EF 451 // : 06 452 // : } 453 // 454 // as a short-term workaround, remove the trailing byte if: 455 // - receiving an even number of bytes == 2*prime-coordinate +2 bytes 456 // - starting byte is 04: uncompressed EC point 457 // - trailing byte is 04: assume it belongs to the next OCTET STRING 458 // 459 // [mis-parsing encountered with v3.5.1, 2016-10-22] 460 // 461 // SoftHSM reports extra two bytes before the uncompressed point 462 // 0x04 || <Length*2+1> 463 // VV< Actual start of point 464 // 00000000 04 41 04 6c c8 57 32 13 02 12 6a 19 23 1d 5a 64 |.A.l.W2...j.#.Zd| 465 // 00000010 33 0c eb 75 4d e8 99 22 92 35 96 b2 39 58 14 1e |3..uM..".5..9X..| 466 // 00000020 19 de ef 32 46 50 68 02 24 62 36 db ed b1 84 7b |...2FPh.$b6....{| 467 // 00000030 93 d8 40 c3 d5 a6 b7 38 16 d2 35 0a 53 11 f9 51 |..@....8..5.S..Q| 468 // 00000040 fc a7 16 |...| 469 func ecPoint(p11lib *pkcs11.Ctx, session pkcs11.SessionHandle, key pkcs11.ObjectHandle) (ecpt, oid []byte, err error) { 470 template := []*pkcs11.Attribute{ 471 pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, nil), 472 pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, nil), 473 } 474 475 attr, err := p11lib.GetAttributeValue(session, key, template) 476 if err != nil { 477 return nil, nil, fmt.Errorf("PKCS11: get(EC point) [%s]", err) 478 } 479 480 for _, a := range attr { 481 if a.Type == pkcs11.CKA_EC_POINT { 482 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)) 483 484 // workarounds, see above 485 if ((len(a.Value) % 2) == 0) && 486 (byte(0x04) == a.Value[0]) && 487 (byte(0x04) == a.Value[len(a.Value)-1]) { 488 logger.Debugf("Detected opencryptoki bug, trimming trailing 0x04") 489 ecpt = a.Value[0 : len(a.Value)-1] // Trim trailing 0x04 490 } else if byte(0x04) == a.Value[0] && byte(0x04) == a.Value[2] { 491 logger.Debugf("Detected SoftHSM bug, trimming leading 0x04 0xXX") 492 ecpt = a.Value[2:len(a.Value)] 493 } else { 494 ecpt = a.Value 495 } 496 } else if a.Type == pkcs11.CKA_EC_PARAMS { 497 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)) 498 499 oid = a.Value 500 } 501 } 502 if oid == nil || ecpt == nil { 503 return nil, nil, fmt.Errorf("CKA_EC_POINT not found, perhaps not an EC Key?") 504 } 505 506 return ecpt, oid, nil 507 } 508 509 func listAttrs(p11lib *pkcs11.Ctx, session pkcs11.SessionHandle, obj pkcs11.ObjectHandle) { 510 var cktype, ckclass uint 511 var ckaid, cklabel []byte 512 513 if p11lib == nil { 514 return 515 } 516 517 template := []*pkcs11.Attribute{ 518 pkcs11.NewAttribute(pkcs11.CKA_CLASS, ckclass), 519 pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, cktype), 520 pkcs11.NewAttribute(pkcs11.CKA_ID, ckaid), 521 pkcs11.NewAttribute(pkcs11.CKA_LABEL, cklabel), 522 } 523 524 // certain errors are tolerated, if value is missing 525 attr, err := p11lib.GetAttributeValue(session, obj, template) 526 if err != nil { 527 logger.Debugf("P11: get(attrlist) [%s]\n", err) 528 } 529 530 for _, a := range attr { 531 // Would be friendlier if the bindings provided a way convert Attribute hex to string 532 logger.Debugf("ListAttr: type %d/0x%x, length %d\n%s", a.Type, a.Type, len(a.Value), hex.Dump(a.Value)) 533 } 534 } 535 536 var ( 537 bigone = new(big.Int).SetInt64(1) 538 idCtr = new(big.Int) 539 idMutex sync.Mutex 540 ) 541 542 func nextIDCtr() *big.Int { 543 idMutex.Lock() 544 idCtr = new(big.Int).Add(idCtr, bigone) 545 idMutex.Unlock() 546 return idCtr 547 }