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