Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve session handling #3

Merged
merged 3 commits into from
Jun 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions common.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import (
"encoding/asn1"
"encoding/base64"
"errors"
pkcs11 "github.com/miekg/pkcs11"
"math/big"
"unsafe"

pkcs11 "github.com/miekg/pkcs11"
)

// ErrMalformedDER represents a failure to decode an ASN.1-encoded message
Expand Down Expand Up @@ -77,11 +78,11 @@ func dsaGeneric(slot uint, key pkcs11.ObjectHandle, mechanism uint, digest []byt
var sigBytes []byte
var sig dsaSignature
mech := []*pkcs11.Mechanism{pkcs11.NewMechanism(mechanism, nil)}
err = withSession(slot, func(session pkcs11.SessionHandle) error {
if err = libHandle.SignInit(session, mech, key); err != nil {
err = withSession(slot, func(session *PKCS11Session) error {
if err = libHandle.SignInit(session.Handle, mech, key); err != nil {
return err
}
sigBytes, err = libHandle.Sign(session, digest)
sigBytes, err = libHandle.Sign(session.Handle, digest)
return err
})
if err != nil {
Expand Down
46 changes: 35 additions & 11 deletions crypto11.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,17 @@ import (
"crypto"
"encoding/json"
"errors"
pkcs11 "github.com/miekg/pkcs11"
"fmt"
"log"
"os"

pkcs11 "github.com/miekg/pkcs11"
)

const (
// DefaultMaxSessions controls the maximum number of concurrent sessions to
// open, unless otherwise specified in the PKCS11Config object.
DefaultMaxSessions = 1024
)

// ErrTokenNotFound represents the failure to find the requested PKCS#11 token
Expand Down Expand Up @@ -119,24 +127,25 @@ type PKCS11PrivateKey struct {

/* Nasty globals */
var libHandle *pkcs11.Ctx
var session pkcs11.SessionHandle
var session *PKCS11Session
var defaultSlot uint
var maxSessions int

// Find a token given its serial number
func findToken(slots []uint, serial string, label string) (uint, uint, error) {
func findToken(slots []uint, serial string, label string) (uint, *pkcs11.TokenInfo, error) {
for _, slot := range slots {
tokenInfo, err := libHandle.GetTokenInfo(slot)
if err != nil {
return 0, 0, err
return 0, nil, err
}
if tokenInfo.SerialNumber == serial {
return slot, tokenInfo.Flags, nil
return slot, &tokenInfo, nil
}
if tokenInfo.Label == label {
return slot, tokenInfo.Flags, nil
return slot, &tokenInfo, nil
}
}
return 0, 0, ErrTokenNotFound
return 0, nil, ErrTokenNotFound
}

// PKCS11Config holds PKCS#11 configuration information.
Expand All @@ -157,6 +166,9 @@ type PKCS11Config struct {

// User PIN (password)
Pin string

// Maximum number of concurrent sessions to open
MaxSessions int
}

// Configure configures PKCS#11 from a PKCS11Config.
Expand Down Expand Up @@ -202,16 +214,28 @@ func Configure(config *PKCS11Config) (*pkcs11.Ctx, error) {
log.Printf("Failed to list PKCS#11 Slots: %s", err.Error())
return nil, err
}
if defaultSlot, flags, err = findToken(slots, config.TokenSerial, config.TokenLabel); err != nil {
slot, token, err := findToken(slots, config.TokenSerial, config.TokenLabel)
if err != nil {
log.Printf("Failed to find Token in any Slot: %s", err.Error())
return nil, err
}
if err = setupSessions(defaultSlot, 0); err != nil {
defaultSlot = slot
flags = token.Flags

maxSessions = config.MaxSessions
if maxSessions == 0 {
maxSessions = DefaultMaxSessions
}
if token.MaxRwSessionCount > 0 && uint(maxSessions) > token.MaxRwSessionCount {
return nil, fmt.Errorf("crypto11: provided max sessions value (%d) exceeds max value the token supports (%d)", maxSessions, token.MaxRwSessionCount)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use log.Fatalf instead since log is already imported.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm merely returning an error here, not trying to make the application exit (which is what log.Fatal will do). Handling the error is up to the calling application.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand, but if you look above, this same function is logging errors in addition to returning errors. I think it's a good idea given that this function handles hardware. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current behavior (i.e.without this PR) is a bit inconsistent; I've created #4 as a placeholder for doing a cleanup at some later date.

}

if err = setupSessions(defaultSlot); err != nil {
return nil, err
}
if err = withSession(defaultSlot, func(session pkcs11.SessionHandle) error {
if err = withSession(defaultSlot, func(session *PKCS11Session) error {
if flags&pkcs11.CKF_LOGIN_REQUIRED != 0 {
err = libHandle.Login(session, pkcs11.CKU_USER, config.Pin)
err = libHandle.Login(session.Handle, pkcs11.CKU_USER, config.Pin)
if err != nil {
log.Printf("Failed to login into PKCS#11 Token: %s", err.Error())
}
Expand Down
15 changes: 8 additions & 7 deletions dsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ package crypto11
import (
"crypto"
"crypto/dsa"
pkcs11 "github.com/miekg/pkcs11"
"io"
"math/big"

pkcs11 "github.com/miekg/pkcs11"
)

// PKCS11PrivateKeyDSA contains a reference to a loaded PKCS#11 DSA private key object.
Expand All @@ -35,14 +36,14 @@ type PKCS11PrivateKeyDSA struct {
}

// Export the public key corresponding to a private DSA key.
func exportDSAPublicKey(session pkcs11.SessionHandle, pubHandle pkcs11.ObjectHandle) (crypto.PublicKey, error) {
func exportDSAPublicKey(session *PKCS11Session, pubHandle pkcs11.ObjectHandle) (crypto.PublicKey, error) {
template := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_PRIME, nil),
pkcs11.NewAttribute(pkcs11.CKA_SUBPRIME, nil),
pkcs11.NewAttribute(pkcs11.CKA_BASE, nil),
pkcs11.NewAttribute(pkcs11.CKA_VALUE, nil),
}
exported, err := libHandle.GetAttributeValue(session, pubHandle, template)
exported, err := libHandle.GetAttributeValue(session.Handle, pubHandle, template)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -71,10 +72,10 @@ func GenerateDSAKeyPair(params *dsa.Parameters) (*PKCS11PrivateKeyDSA, error) {
func GenerateDSAKeyPairOnSlot(slot uint, id []byte, label []byte, params *dsa.Parameters) (*PKCS11PrivateKeyDSA, error) {
var k *PKCS11PrivateKeyDSA
var err error
if err = setupSessions(slot, 0); err != nil {
if err = setupSessions(slot); err != nil {
return nil, err
}
err = withSession(slot, func(session pkcs11.SessionHandle) error {
err = withSession(slot, func(session *PKCS11Session) error {
k, err = GenerateDSAKeyPairOnSession(session, slot, id, label, params)
return err
})
Expand All @@ -84,7 +85,7 @@ func GenerateDSAKeyPairOnSlot(slot uint, id []byte, label []byte, params *dsa.Pa
// GenerateDSAKeyPairOnSession creates a DSA private key using a specified session
//
// Either or both label and/or id can be nil, in which case random values will be generated.
func GenerateDSAKeyPairOnSession(session pkcs11.SessionHandle, slot uint, id []byte, label []byte, params *dsa.Parameters) (*PKCS11PrivateKeyDSA, error) {
func GenerateDSAKeyPairOnSession(session *PKCS11Session, slot uint, id []byte, label []byte, params *dsa.Parameters) (*PKCS11PrivateKeyDSA, error) {
var err error
var pub crypto.PublicKey

Expand Down Expand Up @@ -124,7 +125,7 @@ func GenerateDSAKeyPairOnSession(session pkcs11.SessionHandle, slot uint, id []b
pkcs11.NewAttribute(pkcs11.CKA_ID, id),
}
mech := []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_DSA_KEY_PAIR_GEN, nil)}
pubHandle, privHandle, err := libHandle.GenerateKeyPair(session,
pubHandle, privHandle, err := libHandle.GenerateKeyPair(session.Handle,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a logic behind passing PKCS11Session to some functions and SessionHandle to others?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the functions in crypto11 should operate on *PKCS11Session, whereas all of the functions in pkcs11 accept a pkcs11.SessionHandle.

mech,
publicKeyTemplate,
privateKeyTemplate)
Expand Down
15 changes: 8 additions & 7 deletions ecdsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ import (
"crypto/elliptic"
"encoding/asn1"
"errors"
pkcs11 "github.com/miekg/pkcs11"
"io"
"math/big"

pkcs11 "github.com/miekg/pkcs11"
)

// ErrUnsupportedEllipticCurve is returned when an elliptic curve
Expand Down Expand Up @@ -196,15 +197,15 @@ func unmarshalEcPoint(b []byte, c elliptic.Curve) (x *big.Int, y *big.Int, err e
}

// Export the public key corresponding to a private ECDSA key.
func exportECDSAPublicKey(session pkcs11.SessionHandle, pubHandle pkcs11.ObjectHandle) (crypto.PublicKey, error) {
func exportECDSAPublicKey(session *PKCS11Session, pubHandle pkcs11.ObjectHandle) (crypto.PublicKey, error) {
var err error
var attributes []*pkcs11.Attribute
var pub ecdsa.PublicKey
template := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_ECDSA_PARAMS, nil),
pkcs11.NewAttribute(pkcs11.CKA_EC_POINT, nil),
}
if attributes, err = libHandle.GetAttributeValue(session, pubHandle, template); err != nil {
if attributes, err = libHandle.GetAttributeValue(session.Handle, pubHandle, template); err != nil {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding to the previous comment, I think having two different "handles" (one libHandle and one session.Handle) is a little confusing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the nature of pkcs11 - there are many handles. I'm just maintaining the existing conventions, see PKCS11Object for another example:

// PKCS11Object contains a reference to a loaded PKCS#11 object.
type PKCS11Object struct {
	// The PKCS#11 object handle.
	Handle pkcs11.ObjectHandle

	// The PKCS#11 slot number.
	//
	// This is used internally to find a session handle that can
	// access this object.
	Slot uint
}

return nil, err
}
if pub.Curve, err = unmarshalEcParams(attributes[0].Value); err != nil {
Expand Down Expand Up @@ -235,10 +236,10 @@ func GenerateECDSAKeyPair(c elliptic.Curve) (*PKCS11PrivateKeyECDSA, error) {
func GenerateECDSAKeyPairOnSlot(slot uint, id []byte, label []byte, c elliptic.Curve) (*PKCS11PrivateKeyECDSA, error) {
var k *PKCS11PrivateKeyECDSA
var err error
if err = setupSessions(slot, 0); err != nil {
if err = setupSessions(slot); err != nil {
return nil, err
}
err = withSession(slot, func(session pkcs11.SessionHandle) error {
err = withSession(slot, func(session *PKCS11Session) error {
k, err = GenerateECDSAKeyPairOnSession(session, slot, id, label, c)
return err
})
Expand All @@ -251,7 +252,7 @@ func GenerateECDSAKeyPairOnSlot(slot uint, id []byte, label []byte, c elliptic.C
//
// Only a limited set of named elliptic curves are supported. The
// underlying PKCS#11 implementation may impose further restrictions.
func GenerateECDSAKeyPairOnSession(session pkcs11.SessionHandle, slot uint, id []byte, label []byte, c elliptic.Curve) (*PKCS11PrivateKeyECDSA, error) {
func GenerateECDSAKeyPairOnSession(session *PKCS11Session, slot uint, id []byte, label []byte, c elliptic.Curve) (*PKCS11PrivateKeyECDSA, error) {
var err error
var parameters []byte
var pub crypto.PublicKey
Expand Down Expand Up @@ -290,7 +291,7 @@ func GenerateECDSAKeyPairOnSession(session pkcs11.SessionHandle, slot uint, id [
pkcs11.NewAttribute(pkcs11.CKA_ID, id),
}
mech := []*pkcs11.Mechanism{pkcs11.NewMechanism(pkcs11.CKM_ECDSA_KEY_PAIR_GEN, nil)}
pubHandle, privHandle, err := libHandle.GenerateKeyPair(session,
pubHandle, privHandle, err := libHandle.GenerateKeyPair(session.Handle,
mech,
publicKeyTemplate,
privateKeyTemplate)
Expand Down
21 changes: 11 additions & 10 deletions keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ package crypto11

import (
"crypto"

pkcs11 "github.com/miekg/pkcs11"
)

Expand All @@ -34,8 +35,8 @@ func (object *PKCS11Object) Identify() (id []byte, label []byte, err error) {
pkcs11.NewAttribute(pkcs11.CKA_ID, nil),
pkcs11.NewAttribute(pkcs11.CKA_LABEL, nil),
}
if err = withSession(object.Slot, func(session pkcs11.SessionHandle) error {
a, err = libHandle.GetAttributeValue(session, object.Handle, a)
if err = withSession(object.Slot, func(session *PKCS11Session) error {
a, err = libHandle.GetAttributeValue(session.Handle, object.Handle, a)
return err
}); err != nil {
return nil, nil, err
Expand All @@ -45,7 +46,7 @@ func (object *PKCS11Object) Identify() (id []byte, label []byte, err error) {

// Find a key object. For asymmetric keys this only finds one half so
// callers will call it twice.
func findKey(session pkcs11.SessionHandle, id []byte, label []byte, keyclass uint, keytype uint) (pkcs11.ObjectHandle, error) {
func findKey(session *PKCS11Session, id []byte, label []byte, keyclass uint, keytype uint) (pkcs11.ObjectHandle, error) {
var err error
var handles []pkcs11.ObjectHandle
template := []*pkcs11.Attribute{}
Expand All @@ -61,11 +62,11 @@ func findKey(session pkcs11.SessionHandle, id []byte, label []byte, keyclass uin
if label != nil {
template = append(template, pkcs11.NewAttribute(pkcs11.CKA_LABEL, label))
}
if err = libHandle.FindObjectsInit(session, template); err != nil {
if err = libHandle.FindObjectsInit(session.Handle, template); err != nil {
return 0, err
}
defer libHandle.FindObjectsFinal(session)
if handles, _, err = libHandle.FindObjects(session, 1); err != nil {
defer libHandle.FindObjectsFinal(session.Handle)
if handles, _, err = libHandle.FindObjects(session.Handle, 1); err != nil {
return 0, err
}
if len(handles) == 0 {
Expand All @@ -87,10 +88,10 @@ func FindKeyPair(id []byte, label []byte) (crypto.PrivateKey, error) {
func FindKeyPairOnSlot(slot uint, id []byte, label []byte) (crypto.PrivateKey, error) {
var err error
var k crypto.PrivateKey
if err = setupSessions(slot, 0); err != nil {
if err = setupSessions(slot); err != nil {
return nil, err
}
err = withSession(slot, func(session pkcs11.SessionHandle) error {
err = withSession(slot, func(session *PKCS11Session) error {
k, err = FindKeyPairOnSession(session, slot, id, label)
return err
})
Expand All @@ -100,7 +101,7 @@ func FindKeyPairOnSlot(slot uint, id []byte, label []byte) (crypto.PrivateKey, e
// FindKeyPairOnSession retrieves a previously created asymmetric key, using a specified session.
//
// Either (but not both) of id and label may be nil, in which case they are ignored.
func FindKeyPairOnSession(session pkcs11.SessionHandle, slot uint, id []byte, label []byte) (crypto.PrivateKey, error) {
func FindKeyPairOnSession(session *PKCS11Session, slot uint, id []byte, label []byte) (crypto.PrivateKey, error) {
var err error
var privHandle, pubHandle pkcs11.ObjectHandle
var pub crypto.PublicKey
Expand All @@ -114,7 +115,7 @@ func FindKeyPairOnSession(session pkcs11.SessionHandle, slot uint, id []byte, la
attributes := []*pkcs11.Attribute{
pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, 0),
}
if attributes, err = libHandle.GetAttributeValue(session, privHandle, attributes); err != nil {
if attributes, err = libHandle.GetAttributeValue(session.Handle, privHandle, attributes); err != nil {
return nil, err
}
keyType := bytesToUlong(attributes[0].Value)
Expand Down
8 changes: 2 additions & 6 deletions rand.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@

package crypto11

import (
pkcs11 "github.com/miekg/pkcs11"
)

// A random number reader that uses PKCS#11.
type PKCS11RandReader struct {
}
Expand All @@ -37,8 +33,8 @@ func (reader PKCS11RandReader) Read(data []byte) (n int, err error) {
if libHandle == nil {
return 0, ErrNotConfigured
}
if err = withSession(defaultSlot, func(session pkcs11.SessionHandle) error {
result, err = libHandle.GenerateRandom(session, len(data))
if err = withSession(defaultSlot, func(session *PKCS11Session) error {
result, err = libHandle.GenerateRandom(session.Handle, len(data))
return err
}); err != nil {
return 0, err
Expand Down
Loading