Merge pull request #784 from letsencrypt/fix-pkcs11

Select PKCS11 key by token label + slot id, not by slot description
This commit is contained in:
Jeff Hodges 2015-09-11 17:10:14 -07:00
commit 4ddff2c700
6 changed files with 70 additions and 48 deletions

View File

@ -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) {

View File

@ -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
}

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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"
}