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" } diff --git a/ra/registration-authority_test.go b/ra/registration-authority_test.go index 5cbb69aa7..f3f9cf4a8 100644 --- a/ra/registration-authority_test.go +++ b/ra/registration-authority_test.go @@ -258,7 +258,7 @@ func assertAuthzEqual(t *testing.T, a1, a2 core.Authorization) { if a1.Expires == nil && a2.Expires == nil { return } else if a1.Expires == nil || a2.Expires == nil { - t.Errorf("one and only one of authorization's Expires was nil; ret %s, DB %s", a1, a2) + t.Errorf("one and only one of authorization's Expires was nil; ret %+v, DB %+v", a1, a2) } else { test.Assert(t, a1.Expires.Equal(*a2.Expires), "ret != DB: Expires") } diff --git a/sa/storage-authority_test.go b/sa/storage-authority_test.go index 206c73e6b..64198d473 100644 --- a/sa/storage-authority_test.go +++ b/sa/storage-authority_test.go @@ -433,7 +433,7 @@ func TestMarkCertificateRevoked(t *testing.T) { test.AssertNotError(t, err, "Failed to fetch certificate status") if code != afterStatus.RevokedReason { - t.Errorf("RevokedReasons, expected %s, got %s", code, afterStatus.RevokedReason) + t.Errorf("RevokedReasons, expected %d, got %d", code, afterStatus.RevokedReason) } if !fc.Now().Equal(afterStatus.RevokedDate) { t.Errorf("RevokedData, expected %s, got %s", fc.Now(), afterStatus.RevokedDate)