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

Conversation

cbroglie
Copy link
Contributor

This adds the following functionality:

  • Make the maximum number of sessions configurable
  • Ensure we never open more sessions than the max we specify
  • Timeout instead of (potentially) blocking forever waiting on a session
  • Close idle sessions

These changes were tested using SoftHSM2.

cbroglie added 3 commits June 19, 2018 08:36
This adds the following functionality:
- Ensure we never open more sessions than the max capacity we specify
- Timeout instead of (potentially) blocking forever waiting on a session
- Close idle sessions
cbroglie added a commit to mahrud/gokeyless that referenced this pull request Jun 19, 2018
The new test included in these changes will hang using the upstream
crypto11 package - see ThalesGroup/crypto11#3.
Copy link

@mahrud mahrud left a comment

Choose a reason for hiding this comment

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

Also works with YubiKey when MaxSessions=1.

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

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
}

sessionPoolMutex.Lock()
defer sessionPoolMutex.Unlock()
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 benefit to putting this in the end?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is a very minor (negligible here) performance impact of using defer, so for simple functions without any early returns I've developed the habit of not using it.

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.

return f(session)

ctx, cancel := context.WithTimeout(context.Background(), newSessionTimeout)
defer cancel()
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 probability that this would cut off a session that is active?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good question, but no, the context is only used as a timeout inside Get.

Copy link

Choose a reason for hiding this comment

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

Would still like to test this in practice when we can.

@mahrud
Copy link

mahrud commented Jun 21, 2018

Confirmed that also works with the Thales nShield HSM.

@optnfast optnfast merged commit 9fc0600 into ThalesGroup:master Jun 25, 2018
@optnfast
Copy link
Contributor

Thanks for the PR!

mahrud pushed a commit to mahrud/gokeyless that referenced this pull request Jun 26, 2018
The new test included in these changes will hang using the upstream
crypto11 package - see ThalesGroup/crypto11#3.
cbroglie added a commit to mahrud/gokeyless that referenced this pull request Jun 28, 2018
The new test included in these changes will hang using the upstream
crypto11 package - see ThalesGroup/crypto11#3.
@cbroglie cbroglie deleted the session-handles branch September 12, 2018 02:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants