From 43217216c797b956eaa51453d39a39699dceb40d Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Fri, 11 Sep 2015 18:30:18 -0400 Subject: [PATCH] use slot ids in the cfssl pkcs11 api It was using TokenLabels solely to select slots but those can have duplicates on the same HSM. Instead, use slot IDs with them. --- .../cfssl/crypto/pkcs11key/pkcs11key.go | 67 +++++++++++-------- ca/certificate-authority.go | 10 ++- cmd/shell.go | 9 +-- cmd/single-ocsp/main.go | 11 +-- cmd/single-ocsp/test/gentest.go | 12 ++-- cmd/single-ocsp/test/pkcs11.json | 9 +-- 6 files changed, 70 insertions(+), 48 deletions(-) diff --git a/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs11key/pkcs11key.go b/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs11key/pkcs11key.go index f1cdd8103..a3a3e3c3b 100644 --- a/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs11key/pkcs11key.go +++ b/Godeps/_workspace/src/github.com/cloudflare/cfssl/crypto/pkcs11key/pkcs11key.go @@ -8,6 +8,7 @@ import ( "crypto" "crypto/rsa" "errors" + "fmt" "io" "math/big" @@ -34,9 +35,13 @@ type PKCS11Key struct { // The PKCS#11 library to use module *pkcs11.Ctx - // The name of the slot to be used. + // The slot id of the token to be used. Both this and tokenLabel must match to + // be used. + slotID int + + // The label of the token to be used. // We will automatically search for this in the slot list. - slotDescription string + tokenLabel string // The PIN to be used to log in to the device pin string @@ -49,7 +54,7 @@ type PKCS11Key struct { } // New instantiates a new handle to a PKCS #11-backed key. -func New(module, slot, pin, privLabel string) (ps *PKCS11Key, err error) { +func New(module, tokenLabel, pin, privLabel string, slotID int) (ps *PKCS11Key, err error) { // Set up a new pkcs11 object and initialize it p := pkcs11.New(module) if p == nil { @@ -63,9 +68,10 @@ func New(module, slot, pin, privLabel string) (ps *PKCS11Key, err error) { // Initialize a partial key ps = &PKCS11Key{ - module: p, - slotDescription: slot, - pin: pin, + module: p, + slotID: slotID, + tokenLabel: tokenLabel, + pin: pin, } // Look up the private key @@ -159,35 +165,38 @@ func (ps *PKCS11Key) Destroy() { } func (ps *PKCS11Key) openSession() (session pkcs11.SessionHandle, err error) { - // Find slot by description - slots, err := ps.module.GetSlotList(true) + // Check if there is a PCKS11 token with slots. It has side-effects that + // allow the rest of the code here to work. + _, err = ps.module.GetSlotList(true) if err != nil { return } - for _, slot := range slots { - slotInfo, err := ps.module.GetSlotInfo(slot) - if err != nil { - continue - } - if slotInfo.SlotDescription == ps.slotDescription { - // Open session - session, err = ps.module.OpenSession(slot, pkcs11.CKF_SERIAL_SESSION) - if err != nil { - return session, err - } - - // Login - if err = ps.module.Login(session, pkcs11.CKU_USER, ps.pin); err != nil { - return session, err - } - - return session, err - } + slotID := uint(ps.slotID) + // Look up slot by id + tokenInfo, err := ps.module.GetTokenInfo(slotID) + if err != nil { + return } - err = errors.New("slot not found") - return + // Check that token label matches. + if tokenInfo.Label != ps.tokenLabel { + err = fmt.Errorf("Token label in slot %d was '%s', expected '%s'", + slotID, tokenInfo.Label, ps.tokenLabel) + return + } + // Open session + session, err = ps.module.OpenSession(slotID, pkcs11.CKF_SERIAL_SESSION) + if err != nil { + return session, err + } + + // Login + if err = ps.module.Login(session, pkcs11.CKU_USER, ps.pin); err != nil { + return session, err + } + + return session, err } func (ps *PKCS11Key) closeSession(session pkcs11.SessionHandle) { diff --git a/ca/certificate-authority.go b/ca/certificate-authority.go index 339369425..1b55430d4 100644 --- a/ca/certificate-authority.go +++ b/ca/certificate-authority.go @@ -157,8 +157,16 @@ func loadKey(keyConfig cmd.KeyConfig) (priv crypto.Signer, err error) { } pkcs11Config := keyConfig.PKCS11 + if pkcs11Config.Module == "" || + pkcs11Config.TokenLabel == "" || + pkcs11Config.PIN == "" || + pkcs11Config.PrivateKeyLabel == "" || + pkcs11Config.SlotID == nil { + err = fmt.Errorf("Missing a field in pkcs11Config %#v", pkcs11Config) + return + } priv, err = pkcs11key.New(pkcs11Config.Module, - pkcs11Config.Token, pkcs11Config.PIN, pkcs11Config.Label) + pkcs11Config.TokenLabel, pkcs11Config.PIN, pkcs11Config.PrivateKeyLabel, *pkcs11Config.SlotID) return } diff --git a/cmd/shell.go b/cmd/shell.go index 68912b578..5f50d6e09 100644 --- a/cmd/shell.go +++ b/cmd/shell.go @@ -226,10 +226,11 @@ type KeyConfig struct { // PKCS11Config defines how to load a module for an HSM. type PKCS11Config struct { - Module string - Token string - PIN string - Label string + Module string + TokenLabel string + SlotID *int + PIN string + PrivateKeyLabel string } // TLSConfig reprents certificates and a key for authenticated TLS. diff --git a/cmd/single-ocsp/main.go b/cmd/single-ocsp/main.go index 2e91db44d..b38b6cf61 100644 --- a/cmd/single-ocsp/main.go +++ b/cmd/single-ocsp/main.go @@ -22,10 +22,11 @@ import ( // PKCS11Config defines how to load a module for an HSM. // XXX(rlb@ipv.sx) Copied from certificate-authority.go type PKCS11Config struct { - Module string - Token string - PIN string - Label string + Module string + TokenLabel string + PrivateKeyLabel string + PIN string + SlotID float64 } func readFiles(c *cli.Context) (issuer, responder, target *x509.Certificate, template ocsp.Response, pkcs11 PKCS11Config, err error) { @@ -158,7 +159,7 @@ func main() { cmd.FailOnError(err, "Failed to read files") // Instantiate the private key from PKCS11 - priv, err := pkcs11key.New(pkcs11.Module, pkcs11.Token, pkcs11.PIN, pkcs11.Label) + priv, err := pkcs11key.New(pkcs11.Module, pkcs11.TokenLabel, pkcs11.PIN, pkcs11.PrivateKeyLabel, int(pkcs11.SlotID)) cmd.FailOnError(err, "Failed to load PKCS#11 key") // Populate the remaining fields in the template diff --git a/cmd/single-ocsp/test/gentest.go b/cmd/single-ocsp/test/gentest.go index 5e0ef3db2..30b84b65b 100644 --- a/cmd/single-ocsp/test/gentest.go +++ b/cmd/single-ocsp/test/gentest.go @@ -52,16 +52,18 @@ func toPEM(cert *x509.Certificate) []byte { func main() { // Instantiate the PKCS11 key var pkcs11 struct { - Module string - Token string - PIN string - Label string + Module string + TokenLabel string + PIN string + PrivateKeyLabel string + SlotID float64 } pkcs11Bytes, err := ioutil.ReadFile(pkcs11FileName) panicOnError(err) err = json.Unmarshal(pkcs11Bytes, &pkcs11) panicOnError(err) - p11key, err := pkcs11key.New(pkcs11.Module, pkcs11.Token, pkcs11.PIN, pkcs11.Label) + slotID := int(pkcs11.SlotID) + p11key, err := pkcs11key.New(pkcs11.Module, pkcs11.TokenLabel, pkcs11.PIN, pkcs11.PrivateKeyLabel, slotID) panicOnError(err) // All of the certificates start and end at the same time diff --git a/cmd/single-ocsp/test/pkcs11.json b/cmd/single-ocsp/test/pkcs11.json index 0903ff9fd..e9c777382 100644 --- a/cmd/single-ocsp/test/pkcs11.json +++ b/cmd/single-ocsp/test/pkcs11.json @@ -1,6 +1,7 @@ { - "Module": "/Library/OpenSC/lib/opensc-pkcs11.so", - "Token": "Yubico Yubikey NEO CCID", - "Label": "PIV AUTH key", - "PIN": "123456" + "Module": "/usr/local/Cellar/opensc/0.14.0_1/lib/opensc-pkcs11.so", + "TokenLabel": "PIV_II (PIV Card Holder pin)", + "SlotID": 1, + "PrivateKeyLabel": "SIGN key", + "PIN": "163246" }